mirror of
https://github.com/bitwarden/mobile
synced 2026-01-21 20:03:16 +00:00
Compare commits
1 Commits
v2024.4.0
...
fedemkr-pa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a437a0649 |
11
.github/CODEOWNERS
vendored
11
.github/CODEOWNERS
vendored
@@ -11,16 +11,17 @@
|
||||
.github/workflows @bitwarden/dept-devops
|
||||
|
||||
# DevOps for Version Bumping
|
||||
src/App/Platforms/Android/AndroidManifest.xml
|
||||
src/Android/Properties/AndroidManifest.xml
|
||||
src/iOS.Autofill/Info.plist
|
||||
src/iOS.Extension/Info.plist
|
||||
src/iOS.ShareExtension/Info.plist
|
||||
src/App/Platforms/iOS/Info.plist
|
||||
src/iOS/Info.plist
|
||||
|
||||
## Auth team files ##
|
||||
|
||||
## Platform team files ##
|
||||
appIcons @bitwarden/team-platform-dev
|
||||
build.cake @bitwarden/team-platform-dev
|
||||
|
||||
## Vault team files ##
|
||||
src/watchOS @bitwarden/team-vault-dev
|
||||
@@ -29,14 +30,14 @@ src/watchOS @bitwarden/team-vault-dev
|
||||
src/Core/Services/EmailForwarders @bitwarden/team-tools-dev
|
||||
|
||||
## Crowdin Sync files ##
|
||||
src/Core/Resources/Localization @bitwarden/team-tools-dev
|
||||
src/App/Resources @bitwarden/team-tools-dev
|
||||
src/watchOS/bitwarden/bitwarden\ WatchKit\ Extension/Localization @bitwarden/team-tools-dev
|
||||
store/apple @bitwarden/team-tools-dev
|
||||
store/google @bitwarden/team-tools-dev
|
||||
|
||||
## Locales ##
|
||||
src/Core/Resources/Localization/AppResources.Designer.cs
|
||||
src/Core/Resources/Localization/AppResources.resx
|
||||
src/App/Resources/AppResources.Designer.cs
|
||||
src/App/Resources/AppResources.resx
|
||||
src/watchOS/bitwarden/bitwarden\ WatchKit\ Extension/Localization/en.lproj
|
||||
store/apple/en
|
||||
store/google/en
|
||||
|
||||
BIN
.github/secrets/GoogleService-Info.plist.gpg
vendored
Normal file
BIN
.github/secrets/GoogleService-Info.plist.gpg
vendored
Normal file
Binary file not shown.
BIN
.github/secrets/app_fdroid-keystore.jks.gpg
vendored
Normal file
BIN
.github/secrets/app_fdroid-keystore.jks.gpg
vendored
Normal file
Binary file not shown.
BIN
.github/secrets/app_play-keystore.jks.gpg
vendored
Normal file
BIN
.github/secrets/app_play-keystore.jks.gpg
vendored
Normal file
Binary file not shown.
BIN
.github/secrets/app_upload-keystore.jks.gpg
vendored
Normal file
BIN
.github/secrets/app_upload-keystore.jks.gpg
vendored
Normal file
Binary file not shown.
BIN
.github/secrets/bitwarden-mobile-key.p12.gpg
vendored
Normal file
BIN
.github/secrets/bitwarden-mobile-key.p12.gpg
vendored
Normal file
Binary file not shown.
BIN
.github/secrets/dist_autofill.mobileprovision.gpg
vendored
Normal file
BIN
.github/secrets/dist_autofill.mobileprovision.gpg
vendored
Normal file
Binary file not shown.
BIN
.github/secrets/dist_bitwarden.mobileprovision.gpg
vendored
Normal file
BIN
.github/secrets/dist_bitwarden.mobileprovision.gpg
vendored
Normal file
Binary file not shown.
BIN
.github/secrets/dist_extension.mobileprovision.gpg
vendored
Normal file
BIN
.github/secrets/dist_extension.mobileprovision.gpg
vendored
Normal file
Binary file not shown.
BIN
.github/secrets/dist_share_extension.mobileprovision.gpg
vendored
Normal file
BIN
.github/secrets/dist_share_extension.mobileprovision.gpg
vendored
Normal file
Binary file not shown.
BIN
.github/secrets/dist_watch_app.mobileprovision.gpg
vendored
Normal file
BIN
.github/secrets/dist_watch_app.mobileprovision.gpg
vendored
Normal file
Binary file not shown.
BIN
.github/secrets/dist_watch_app_extension.mobileprovision.gpg
vendored
Normal file
BIN
.github/secrets/dist_watch_app_extension.mobileprovision.gpg
vendored
Normal file
Binary file not shown.
3
.github/secrets/google-services.json.gpg
vendored
Normal file
3
.github/secrets/google-services.json.gpg
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<EFBFBD>
|
||||
K<>Y#<23>(<28><><EFBFBD><EFBFBD>EI߄T?)l<><6C><EFBFBD><18><><10>"=<3D>|<7C>'e<><0E>m<EFBFBD>/~<7E><>'F<><46>><3E><><EFBFBD><EFBFBD>l<EFBFBD>b<EFBFBD>[<5B>+R<><52>iL<69><4C>"<22><><EFBFBD>~V:<3A><>p<EFBFBD>a<17>ڵel%8t<38><74>튖<EFBFBD>y<<3C>n<EFBFBD><6E><EFBFBD>aU<61>w<16>JD<4A><44><1F><>We<57>9<EFBFBD><39><EFBFBD><EFBFBD><x8d<38>O<EFBFBD>j\<14>ד<EFBFBD><D793><EFBFBD>Vq<56><71>
|
||||
Ǻ<EFBFBD>-<2D>#<23><><11><>]$<24>(<28>l,<2C>Br<42><02><>d<><64><EFBFBD>a-<2D><><EFBFBD>:<3A><>:<3A><04>9b,!Em<02><19><>Qf<>D<EFBFBD>g<EFBFBD><06><0E>x(P<>ȡ~<7E><EFBFBD><CDB9> <09><>[<06><>!:<3A>;f<><66>
|
||||
BIN
.github/secrets/iphone-distribution-cert.p12.gpg
vendored
Normal file
BIN
.github/secrets/iphone-distribution-cert.p12.gpg
vendored
Normal file
Binary file not shown.
BIN
.github/secrets/play_creds.json.gpg
vendored
Normal file
BIN
.github/secrets/play_creds.json.gpg
vendored
Normal file
Binary file not shown.
BIN
.github/secrets/store_fdroid-keystore.jks.gpg
vendored
Normal file
BIN
.github/secrets/store_fdroid-keystore.jks.gpg
vendored
Normal file
Binary file not shown.
350
.github/workflows/build-beta.yml
vendored
350
.github/workflows/build-beta.yml
vendored
@@ -1,350 +0,0 @@
|
||||
---
|
||||
name: Build Beta
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
description: 'Branch or tag to build'
|
||||
required: true
|
||||
default: 'main'
|
||||
type: string
|
||||
|
||||
env:
|
||||
main_app_folder_path: src/App
|
||||
main_app_project_path: src/App/App.csproj
|
||||
target-net-version: net8.0
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
name: Setup
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
rc_branch_exists: ${{ steps.branch-check.outputs.rc_branch_exists }}
|
||||
hotfix_branch_exists: ${{ steps.branch-check.outputs.hotfix_branch_exists }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
submodules: 'true'
|
||||
|
||||
- name: Check if special branches exist
|
||||
id: branch-check
|
||||
run: |
|
||||
if [[ $(git ls-remote --heads origin rc) ]]; then
|
||||
echo "rc_branch_exists=1" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "rc_branch_exists=0" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
if [[ $(git ls-remote --heads origin hotfix-rc) ]]; then
|
||||
echo "hotfix_branch_exists=1" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "hotfix_branch_exists=0" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
ios:
|
||||
name: Apple iOS
|
||||
runs-on: macos-13
|
||||
needs: setup
|
||||
env:
|
||||
ios_folder_path: src/App/Platforms/iOS
|
||||
app_output_name: App
|
||||
app_ci_output_filename: App_x64_Debug
|
||||
steps:
|
||||
- name: Set XCode version
|
||||
uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0
|
||||
with:
|
||||
xcode-version: 15.1
|
||||
|
||||
- name: Setup NuGet
|
||||
uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0
|
||||
with:
|
||||
nuget-version: 6.4.0
|
||||
|
||||
- name: Set up .NET
|
||||
uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0
|
||||
with:
|
||||
dotnet-version: '8.0.x'
|
||||
|
||||
# This step might be obsolete at some point as .NET MAUI workloads
|
||||
# are starting to come pre-installed on the GH Actions build agents.
|
||||
- name: Install MAUI Workload
|
||||
run: dotnet workload install maui --ignore-failed-sources
|
||||
|
||||
- name: Print environment
|
||||
run: |
|
||||
nuget help | grep Version
|
||||
dotnet --info
|
||||
echo "GitHub ref: $GITHUB_REF"
|
||||
echo "GitHub event: $GITHUB_EVENT"
|
||||
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ inputs.ref }}
|
||||
submodules: 'true'
|
||||
|
||||
- name: Login to Azure - CI Subscription
|
||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||
|
||||
- name: Retrieve secrets
|
||||
id: retrieve-secrets
|
||||
uses: bitwarden/gh-actions/get-keyvault-secrets@main
|
||||
with:
|
||||
keyvault: "bitwarden-ci"
|
||||
secrets: "appcenter-ios-token"
|
||||
|
||||
- name: Download Provisioning Profiles secrets
|
||||
env:
|
||||
ACCOUNT_NAME: bitwardenci
|
||||
CONTAINER_NAME: profiles
|
||||
run: |
|
||||
mkdir -p $HOME/secrets
|
||||
profiles=(
|
||||
"dist_beta_autofill.mobileprovision"
|
||||
"dist_beta_bitwarden.mobileprovision"
|
||||
"dist_beta_extension.mobileprovision"
|
||||
"dist_beta_share_extension.mobileprovision"
|
||||
"dist_beta_bitwarden_watch_app.mobileprovision"
|
||||
"dist_beta_bitwarden_watch_app_extension.mobileprovision"
|
||||
)
|
||||
|
||||
for FILE in "${profiles[@]}"
|
||||
do
|
||||
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME --name $FILE \
|
||||
--file $HOME/secrets/$FILE --output none
|
||||
done
|
||||
|
||||
- name: Download Google Services secret
|
||||
env:
|
||||
ACCOUNT_NAME: bitwardenci
|
||||
CONTAINER_NAME: mobile
|
||||
FILE: GoogleService-Info.plist
|
||||
run: |
|
||||
mkdir -p $HOME/secrets
|
||||
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME --name $FILE \
|
||||
--file $HOME/secrets/$FILE --output none
|
||||
|
||||
- name: Increment version
|
||||
run: |
|
||||
BUILD_NUMBER=$((100 + $GITHUB_RUN_NUMBER))
|
||||
echo "##### Setting CFBundleVersion $BUILD_NUMBER"
|
||||
|
||||
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>/' ./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.ShareExtension/Info.plist
|
||||
cd src/watchOS/bitwarden
|
||||
agvtool new-version -all $BUILD_NUMBER
|
||||
|
||||
- name: Update Entitlements
|
||||
run: |
|
||||
echo "##### Updating Entitlements"
|
||||
perl -0777 -pi.bak -e 's/<key>aps-environment<\/key>\s*<string>development<\/string>/<key>aps-environment<\/key>\n\t<string>beta<\/string>/' ./${{ env.ios_folder_path }}/Entitlements.plist
|
||||
|
||||
- name: Get certificates
|
||||
run: |
|
||||
mkdir -p $HOME/certificates
|
||||
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/ios-distribution |
|
||||
jq -r .value | base64 -d > $HOME/certificates/ios-distribution.p12
|
||||
|
||||
- name: Set up Keychain
|
||||
env:
|
||||
KEYCHAIN_PASSWORD: ${{ secrets.IOS_KEYCHAIN_PASSWORD }}
|
||||
MOBILE_KEY_PASSWORD: ${{ secrets.IOS_KEY_PASSWORD }}
|
||||
DIST_CERT_PASSWORD: ${{ secrets.IOS_DIST_CERT_PASSWORD }}
|
||||
run: |
|
||||
security create-keychain -p $KEYCHAIN_PASSWORD build.keychain
|
||||
security default-keychain -s build.keychain
|
||||
security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain
|
||||
security set-keychain-settings -lut 1200 build.keychain
|
||||
|
||||
security import $HOME/certificates/ios-distribution.p12 -k build.keychain -P "" -T /usr/bin/codesign \
|
||||
-T /usr/bin/security
|
||||
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain
|
||||
|
||||
- name: Set up provisioning profiles
|
||||
run: |
|
||||
AUTOFILL_PROFILE_PATH=$HOME/secrets/dist_beta_autofill.mobileprovision
|
||||
BITWARDEN_PROFILE_PATH=$HOME/secrets/dist_beta_bitwarden.mobileprovision
|
||||
EXTENSION_PROFILE_PATH=$HOME/secrets/dist_beta_extension.mobileprovision
|
||||
SHARE_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_beta_share_extension.mobileprovision
|
||||
WATCH_APP_PROFILE_PATH=$HOME/secrets/dist_beta_bitwarden_watch_app.mobileprovision
|
||||
WATCH_APP_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_beta_bitwarden_watch_app_extension.mobileprovision
|
||||
PROFILES_DIR_PATH=$HOME/Library/MobileDevice/Provisioning\ Profiles
|
||||
|
||||
mkdir -p "$PROFILES_DIR_PATH"
|
||||
|
||||
AUTOFILL_UUID=$(grep UUID -A1 -a $AUTOFILL_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
|
||||
cp $AUTOFILL_PROFILE_PATH "$PROFILES_DIR_PATH/$AUTOFILL_UUID.mobileprovision"
|
||||
|
||||
BITWARDEN_UUID=$(grep UUID -A1 -a $BITWARDEN_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
|
||||
cp $BITWARDEN_PROFILE_PATH "$PROFILES_DIR_PATH/$BITWARDEN_UUID.mobileprovision"
|
||||
|
||||
EXTENSION_UUID=$(grep UUID -A1 -a $EXTENSION_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
|
||||
cp $EXTENSION_PROFILE_PATH "$PROFILES_DIR_PATH/$EXTENSION_UUID.mobileprovision"
|
||||
|
||||
SHARE_EXTENSION_UUID=$(grep UUID -A1 -a $SHARE_EXTENSION_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
|
||||
cp $SHARE_EXTENSION_PROFILE_PATH "$PROFILES_DIR_PATH/$SHARE_EXTENSION_UUID.mobileprovision"
|
||||
|
||||
WATCH_APP_UUID=$(grep UUID -A1 -a $WATCH_APP_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
|
||||
cp $WATCH_APP_PROFILE_PATH "$PROFILES_DIR_PATH/$WATCH_APP_UUID.mobileprovision"
|
||||
|
||||
WATCH_APP_EXTENSION_UUID=$(grep UUID -A1 -a $WATCH_APP_EXTENSION_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
|
||||
cp $WATCH_APP_EXTENSION_PROFILE_PATH "$PROFILES_DIR_PATH/$WATCH_APP_EXTENSION_UUID.mobileprovision"
|
||||
|
||||
- name: Restore packages
|
||||
run: |
|
||||
dotnet restore
|
||||
dotnet tool restore
|
||||
|
||||
- name: Setup iOS build CAKE (Testing)
|
||||
run: dotnet cake build.cake --target iOS --variant beta
|
||||
|
||||
- name: Bulid WatchApp
|
||||
run: |
|
||||
echo "##### Build WatchApp with Release Configuration"
|
||||
xcodebuild archive -workspace ./src/watchOS/bitwarden/bitwarden.xcodeproj/project.xcworkspace -configuration Release -scheme bitwarden\ WatchKit\ App -archivePath ./src/watchOS/bitwarden
|
||||
|
||||
echo "##### Done"
|
||||
|
||||
- name: Archive Build for App Store
|
||||
shell: pwsh
|
||||
run: |
|
||||
Write-Output "##### Archive for Release ios-arm64"
|
||||
dotnet publish ${{ env.main_app_project_path }} -c Release -f ${{ env.target-net-version }}-ios /p:RuntimeIdentifier=ios-arm64 /p:ArchiveOnBuild=true /p:MtouchUseLlvm=false
|
||||
|
||||
Write-Output "##### Done"
|
||||
|
||||
- name: Archive Build for Mobile Automation
|
||||
shell: pwsh
|
||||
run: |
|
||||
Write-Output "##### Archive Debug for iossimulator-x64"
|
||||
dotnet build ${{ env.main_app_project_path }} -c Debug -f ${{ env.target-net-version }}-ios /p:RuntimeIdentifier=iossimulator-x64 /p:ArchiveOnBuild=true /p:MtouchUseLlvm=false
|
||||
|
||||
Write-Output "##### Done"
|
||||
ls ~/Library/Developer/Xcode/Archives
|
||||
|
||||
- name: Export .ipa for App Store
|
||||
env:
|
||||
EXPORT_OPTIONS_PATH: ./.github/resources/export-options-app-store.plist
|
||||
EXPORT_PATH: ./bitwarden-export
|
||||
run: |
|
||||
ARCHIVE_PATH="$HOME/Library/Developer/Xcode/Archives/*/*.xcarchive"
|
||||
|
||||
xcodebuild -exportArchive -archivePath $ARCHIVE_PATH -exportPath $EXPORT_PATH \
|
||||
-exportOptionsPlist $EXPORT_OPTIONS_PATH
|
||||
|
||||
- name: Export .app for Automation CI
|
||||
env:
|
||||
ARCHIVE_PATH: ./${{ env.main_app_folder_path }}/bin/Debug/${{ env.target-net-version }}-ios/iossimulator-x64
|
||||
EXPORT_PATH: ./bitwarden-export
|
||||
run: |
|
||||
zip -r -q ${{ env.app_ci_output_filename }}.app.zip $ARCHIVE_PATH
|
||||
mv ${{ env.app_ci_output_filename }}.app.zip $EXPORT_PATH
|
||||
|
||||
- name: Show Bitwarden Export
|
||||
shell: bash
|
||||
run: ls -a -R ./bitwarden-export
|
||||
|
||||
- name: Copy all dSYMs files to upload
|
||||
env:
|
||||
EXPORT_PATH: ./bitwarden-export
|
||||
WATCH_ARCHIVE_DSYMS_PATH: ./src/watchOS/bitwarden.xcarchive/dSYMs/
|
||||
WATCH_DSYMS_EXPORT_PATH: ./bitwarden-export/Watch_dSYMs
|
||||
run: |
|
||||
ARCHIVE_DSYMS_PATH="$HOME/Library/Developer/Xcode/Archives/*/*.xcarchive/dSYMs"
|
||||
|
||||
cp -r -v $ARCHIVE_DSYMS_PATH $EXPORT_PATH
|
||||
mkdir $WATCH_DSYMS_EXPORT_PATH
|
||||
cp -r -v $WATCH_ARCHIVE_DSYMS_PATH $WATCH_DSYMS_EXPORT_PATH
|
||||
|
||||
- name: Upload App Store .ipa & dSYMs artifacts
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
with:
|
||||
name: Bitwarden iOS
|
||||
path: |
|
||||
./bitwarden-export/Bitwarden*.ipa
|
||||
./bitwarden-export/dSYMs/*.*
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload .app file for Automation CI
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
with:
|
||||
name: ${{ env.app_ci_output_filename }}.app.zip
|
||||
path: ./bitwarden-export/${{ env.app_ci_output_filename }}.app.zip
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Install AppCenter CLI
|
||||
run: npm install -g appcenter-cli
|
||||
|
||||
- name: Upload dSYMs to App Center
|
||||
env:
|
||||
APPCENTER_IOS_TOKEN: ${{ steps.retrieve-secrets.outputs.appcenter-ios-token }}
|
||||
run: appcenter crashes upload-symbols -a bitwarden/bitwarden -s "./bitwarden-export/dSYMs" --token $APPCENTER_IOS_TOKEN
|
||||
|
||||
- name: Upload Watch dSYMs to Firebase Crashlytics
|
||||
run: |
|
||||
echo "##### Uploading Watch dSYMs to Firebase"
|
||||
find "$HOME/Library/Developer/XCode/DerivedData" -name "upload-symbols" -exec chmod +x {} \; -exec {} -gsp "./src/watchOS/bitwarden/GoogleService-Info.plist" -p ios "./bitwarden-export/Watch_dSYMs" \;
|
||||
|
||||
- name: Validate app in App Store
|
||||
env:
|
||||
APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }}
|
||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||
run: |
|
||||
xcrun altool --validate-app --type ios --file "./bitwarden-export/Bitwarden Beta.ipa" \
|
||||
--username "$APPLE_ID_USERNAME" --password "$APPLE_ID_PASSWORD"
|
||||
shell: bash
|
||||
|
||||
- name: Deploy to App Store
|
||||
env:
|
||||
APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }}
|
||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||
run: |
|
||||
xcrun altool --upload-app --type ios --file "./bitwarden-export/Bitwarden Beta.ipa" \
|
||||
--username "$APPLE_ID_USERNAME" --password "$APPLE_ID_PASSWORD"
|
||||
|
||||
check-failures:
|
||||
name: Check for failures
|
||||
if: always()
|
||||
runs-on: ubuntu-22.04
|
||||
needs:
|
||||
- setup
|
||||
- ios
|
||||
steps:
|
||||
- name: Check if any job failed
|
||||
if: |
|
||||
(github.ref == 'refs/heads/main'
|
||||
|| github.ref == 'refs/heads/rc'
|
||||
|| github.ref == 'refs/heads/hotfix-rc')
|
||||
&& contains(needs.*.result, 'failure')
|
||||
run: exit 1
|
||||
|
||||
- name: Login to Azure - CI Subscription
|
||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||
if: failure()
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||
|
||||
- name: Retrieve secrets
|
||||
id: retrieve-secrets
|
||||
uses: bitwarden/gh-actions/get-keyvault-secrets@main
|
||||
if: failure()
|
||||
with:
|
||||
keyvault: "bitwarden-ci"
|
||||
secrets: "devops-alerts-slack-webhook-url"
|
||||
|
||||
- name: Notify Slack on failure
|
||||
uses: act10ns/slack@ed1309ab9862e57e9e583e51c7889486b9a00b0f # v2.0.0
|
||||
if: failure()
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }}
|
||||
with:
|
||||
status: ${{ job.status }}
|
||||
407
.github/workflows/build.yml
vendored
407
.github/workflows/build.yml
vendored
@@ -31,7 +31,6 @@ jobs:
|
||||
- name: Print lines of code
|
||||
run: cloc --vcs git --exclude-dir Resources,store,test,Properties --include-lang C#,XAML
|
||||
|
||||
|
||||
setup:
|
||||
name: Setup
|
||||
runs-on: ubuntu-22.04
|
||||
@@ -59,7 +58,6 @@ jobs:
|
||||
echo "hotfix_branch_exists=0" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
|
||||
android:
|
||||
name: Android
|
||||
runs-on: windows-2022
|
||||
@@ -69,8 +67,7 @@ jobs:
|
||||
matrix:
|
||||
variant: ["prod", "qa"]
|
||||
env:
|
||||
android_folder_path: src\App\Platforms\Android
|
||||
android_folder_path_bash: src/App/Platforms/Android
|
||||
android_folder_path: src/App/Platforms/Android
|
||||
steps:
|
||||
- name: Setup NuGet
|
||||
uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0
|
||||
@@ -85,7 +82,7 @@ jobs:
|
||||
- name: Set up MSBuild
|
||||
uses: microsoft/setup-msbuild@ede762b26a2de8d110bb5a3db4d7e0e080c0e917 # v1.3.3
|
||||
|
||||
# This step might be obsolete at some point as .NET MAUI workloads
|
||||
# This step might be obsolete at some point as .NET MAUI workloads
|
||||
# are starting to come pre-installed on the GH Actions build agents.
|
||||
- name: Install MAUI Workload
|
||||
run: dotnet workload install maui --ignore-failed-sources
|
||||
@@ -96,8 +93,7 @@ jobs:
|
||||
- name: Install Microsoft OpenJDK 11
|
||||
run: |
|
||||
choco install microsoft-openjdk11 --no-progress
|
||||
Write-Output "JAVA_HOME=$(Get-ChildItem -Path 'C:\Program Files\Microsoft\jdk*' | `
|
||||
Select -First 1 -ExpandProperty FullName)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
Write-Output "JAVA_HOME=$(Get-ChildItem -Path 'C:\Program Files\Microsoft\jdk*' | Select -First 1 -ExpandProperty FullName)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
Write-Output "Java Home: $env:JAVA_HOME"
|
||||
|
||||
- name: Print environment
|
||||
@@ -113,43 +109,39 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Login to Azure - CI Subscription
|
||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||
|
||||
- name: Download secrets
|
||||
- name: Decrypt secrets
|
||||
env:
|
||||
ACCOUNT_NAME: bitwardenci
|
||||
CONTAINER_NAME: mobile
|
||||
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }}
|
||||
run: |
|
||||
mkdir -p $HOME/secrets
|
||||
mkdir -p ~/secrets
|
||||
|
||||
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
|
||||
--name app_play-keystore.jks --file ./${{ env.android_folder_path_bash }}/app_play-keystore.jks --output none
|
||||
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
|
||||
--name app_upload-keystore.jks --file ./${{ env.android_folder_path_bash }}/app_upload-keystore.jks --output none
|
||||
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
|
||||
--name play_creds.json --file $HOME/secrets/play_creds.json --output none
|
||||
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||
--output ./${{ env.main_app_folder_path }}/app_play-keystore.jks ./.github/secrets/app_play-keystore.jks.gpg
|
||||
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||
--output ./${{ env.main_app_folder_path }}/app_upload-keystore.jks ./.github/secrets/app_upload-keystore.jks.gpg
|
||||
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||
--output $HOME/secrets/play_creds.json ./.github/secrets/play_creds.json.gpg
|
||||
shell: bash
|
||||
|
||||
- name: Download secrets - Google Services
|
||||
- name: Decrypt secrets - Google Services
|
||||
if: ${{ matrix.variant == 'prod' }}
|
||||
env:
|
||||
ACCOUNT_NAME: bitwardenci
|
||||
CONTAINER_NAME: mobile
|
||||
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }}
|
||||
run: |
|
||||
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
|
||||
--name google-services.json --file ./${{ env.android_folder_path_bash }}/google-services.json --output none
|
||||
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||
--output ./${{ env.android_folder_path }}/google-services.json ./.github/secrets/google-services.json.gpg
|
||||
shell: bash
|
||||
|
||||
- name: Increment version
|
||||
run: |
|
||||
BUILD_NUMBER=$((3000 + $GITHUB_RUN_NUMBER))
|
||||
echo "##### Setting Android Version Code to $BUILD_NUMBER" | tee -a $GITHUB_STEP_SUMMARY
|
||||
|
||||
echo "########################################"
|
||||
echo "##### Setting Version Code $BUILD_NUMBER"
|
||||
echo "########################################"
|
||||
|
||||
sed -i "s/android:versionCode=\"1\"/android:versionCode=\"$BUILD_NUMBER\"/" \
|
||||
./${{ env.android_folder_path_bash }}/AndroidManifest.xml
|
||||
./${{ env.android_folder_path }}/AndroidManifest.xml
|
||||
shell: bash
|
||||
|
||||
- name: Restore packages
|
||||
@@ -158,75 +150,83 @@ jobs:
|
||||
- name: Restore tools
|
||||
run: dotnet tool restore
|
||||
|
||||
# - name: Run Core tests
|
||||
# run: |
|
||||
# dotnet test test/Core.Test/Core.Test.csproj --logger "trx;LogFileName=test-results.trx" `
|
||||
# /p:CustomConstants=UT
|
||||
# - name: Verify Format
|
||||
# run: dotnet tool run dotnet-format --check
|
||||
|
||||
# - name: Report test results
|
||||
# uses: dorny/test-reporter@eaa763f6ffc21c7a37837f56cd5f9737f27fc6c8 # v1.8.0
|
||||
# if: always()
|
||||
# with:
|
||||
# name: Test Results
|
||||
# path: "**/test-results.trx"
|
||||
# reporter: dotnet-trx
|
||||
# fail-on-error: true
|
||||
- name: Run Core tests
|
||||
run: dotnet test test/Core.Test/Core.Test.csproj --logger "trx;LogFileName=test-results.trx" /p:CustomConstants=UT
|
||||
|
||||
- name: Report test results
|
||||
uses: dorny/test-reporter@eaa763f6ffc21c7a37837f56cd5f9737f27fc6c8 # v1.8.0
|
||||
if: always()
|
||||
with:
|
||||
name: Test Results
|
||||
path: "**/test-results.trx"
|
||||
reporter: dotnet-trx
|
||||
fail-on-error: true
|
||||
|
||||
- name: Build Play Store publisher
|
||||
if: ${{ matrix.variant == 'prod' }}
|
||||
run: dotnet build .\store\google\Publisher\Publisher.csproj /p:Configuration=Release
|
||||
run: dotnet build ./store/google/Publisher/Publisher.csproj -p:Configuration=Release
|
||||
|
||||
- name: Setup Android build (${{ matrix.variant }})
|
||||
run: dotnet cake build.cake --target Android --variant ${{ matrix.variant }}
|
||||
|
||||
- name: Build & Sign Android
|
||||
- name: Build Android
|
||||
run: |
|
||||
$configuration = "Release";
|
||||
$projToBuild = $($env:GITHUB_WORKSPACE + "/${{ env.main_app_project_path }}");
|
||||
|
||||
Write-Output "########################################"
|
||||
Write-Output "##### Build $configuration Configuration"
|
||||
Write-Output "########################################"
|
||||
|
||||
dotnet build $projToBuild -c $configuration -f ${{ env.target-net-version }}-android
|
||||
|
||||
- name: Sign Android Build
|
||||
env:
|
||||
PLAY_KEYSTORE_PASSWORD: ${{ secrets.PLAY_KEYSTORE_PASSWORD }}
|
||||
UPLOAD_KEYSTORE_PASSWORD: ${{ secrets.UPLOAD_KEYSTORE_PASSWORD }}
|
||||
run: |
|
||||
$projToBuild = "$($env:GITHUB_WORKSPACE)/${{ env.main_app_project_path }}";
|
||||
$projToBuild = $($env:GITHUB_WORKSPACE + "/${{ env.main_app_project_path }}");
|
||||
$packageName = "com.x8bit.bitwarden";
|
||||
|
||||
if ("${{ matrix.variant }}" -ne "prod")
|
||||
{
|
||||
$packageName = "com.x8bit.bitwarden.${{ matrix.variant }}";
|
||||
}
|
||||
Write-Output "########################################"
|
||||
Write-Output "##### Sign Google Play Bundle Release Configuration"
|
||||
Write-Output "########################################"
|
||||
|
||||
$signingUploadKeyStore = "$($env:GITHUB_WORKSPACE)\${{ env.android_folder_path }}\app_upload-keystore.jks"
|
||||
dotnet publish $projToBuild -c Release -f ${{ env.target-net-version }}-android `
|
||||
/p:AndroidPackageFormats=aab `
|
||||
/p:AndroidKeyStore=true `
|
||||
/p:AndroidSigningKeyStore=$signingUploadKeyStore `
|
||||
/p:AndroidSigningKeyAlias=upload `
|
||||
/p:AndroidSigningKeyPass="$($env:UPLOAD_KEYSTORE_PASSWORD)" `
|
||||
/p:AndroidSigningStorePass="$($env:UPLOAD_KEYSTORE_PASSWORD)" --no-restore
|
||||
dotnet publish $projToBuild -c Release -f ${{ env.target-net-version }}-android /p:AndroidPackageFormats=aab /p:AndroidKeyStore=true /p:AndroidSigningKeyStore=$("app_upload-keystore.jks") /p:AndroidSigningKeyAlias=upload /p:AndroidSigningKeyPass="$($env:UPLOAD_KEYSTORE_PASSWORD)" /p:AndroidSigningStorePass="$($env:UPLOAD_KEYSTORE_PASSWORD)" --no-restore
|
||||
|
||||
Write-Output "########################################"
|
||||
Write-Output "##### Copy Google Play Bundle to project root"
|
||||
Write-Output "########################################"
|
||||
|
||||
$signedAabPath = "$($env:GITHUB_WORKSPACE)\${{ env.main_app_folder_path }}\bin\Release\${{ env.target-net-version }}-android\publish\$($packageName)-Signed.aab";
|
||||
$signedAabDestPath = "$($env:GITHUB_WORKSPACE)\$($packageName).aab";
|
||||
$signedAabPath = $($env:GITHUB_WORKSPACE + "/${{ env.main_app_folder_path }}/bin/Release/${{ env.target-net-version }}-android/publish/$($packageName)-Signed.aab");
|
||||
$signedAabDestPath = $($env:GITHUB_WORKSPACE + "/$($packageName).aab");
|
||||
Copy-Item $signedAabPath $signedAabDestPath
|
||||
|
||||
Write-Output "########################################"
|
||||
Write-Output "##### Sign APK Release Configuration"
|
||||
Write-Output "########################################"
|
||||
|
||||
$signingPlayKeyStore = "$($env:GITHUB_WORKSPACE)\${{ env.android_folder_path }}\app_play-keystore.jks"
|
||||
dotnet publish $projToBuild -c Release -f ${{ env.target-net-version }}-android `
|
||||
/p:AndroidKeyStore=true `
|
||||
/p:AndroidSigningKeyStore=$signingPlayKeyStore `
|
||||
/p:AndroidSigningKeyAlias=bitwarden `
|
||||
/p:AndroidSigningKeyPass="$($env:PLAY_KEYSTORE_PASSWORD)" `
|
||||
/p:AndroidSigningStorePass="$($env:PLAY_KEYSTORE_PASSWORD)" --no-restore
|
||||
dotnet publish $projToBuild -c Release -f ${{ env.target-net-version }}-android /p:AndroidKeyStore=true /p:AndroidSigningKeyStore=$("app_play-keystore.jks") /p:AndroidSigningKeyAlias=bitwarden /p:AndroidSigningKeyPass="$($env:PLAY_KEYSTORE_PASSWORD)" /p:AndroidSigningStorePass="$($env:PLAY_KEYSTORE_PASSWORD)" --no-restore
|
||||
|
||||
Write-Output "########################################"
|
||||
Write-Output "##### Copy Release APK to project root"
|
||||
Write-Output "########################################"
|
||||
|
||||
$signedApkPath = $($env:GITHUB_WORKSPACE + "/${{ env.main_app_folder_path }}/bin/Release/${{ env.target-net-version }}-android/publish/$($packageName)-Signed.apk");
|
||||
$signedApkDestPath = $($env:GITHUB_WORKSPACE + "/$($packageName).apk");
|
||||
|
||||
$signedApkPath = "$($env:GITHUB_WORKSPACE)\${{ env.main_app_folder_path }}\bin\Release\${{ env.target-net-version }}-android\publish\$($packageName)-Signed.apk";
|
||||
$signedApkDestPath = "$($env:GITHUB_WORKSPACE)\$($packageName).apk";
|
||||
Copy-Item $signedApkPath $signedApkDestPath
|
||||
|
||||
- name: Upload Prod .aab artifact
|
||||
if: ${{ matrix.variant == 'prod' }}
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
|
||||
with:
|
||||
name: com.x8bit.bitwarden.aab
|
||||
path: ./com.x8bit.bitwarden.aab
|
||||
@@ -234,7 +234,7 @@ jobs:
|
||||
|
||||
- name: Upload Prod .apk artifact
|
||||
if: ${{ matrix.variant == 'prod' }}
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
|
||||
with:
|
||||
name: com.x8bit.bitwarden.apk
|
||||
path: ./com.x8bit.bitwarden.apk
|
||||
@@ -242,7 +242,7 @@ jobs:
|
||||
|
||||
- name: Upload Other .apk artifact
|
||||
if: ${{ matrix.variant != 'prod' }}
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
|
||||
with:
|
||||
name: 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
|
||||
if: ${{ matrix.variant == 'prod' }}
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
|
||||
with:
|
||||
name: bw-android-apk-sha256.txt
|
||||
path: ./bw-android-apk-sha256.txt
|
||||
@@ -270,7 +270,7 @@ jobs:
|
||||
|
||||
- name: Upload .apk sha file for other
|
||||
if: ${{ matrix.variant != 'prod' }}
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
|
||||
with:
|
||||
name: bw-android-${{ matrix.variant }}-apk-sha256.txt
|
||||
path: ./bw-android-${{ matrix.variant }}-apk-sha256.txt
|
||||
@@ -283,20 +283,20 @@ jobs:
|
||||
|| (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0)
|
||||
|| github.ref == 'refs/heads/hotfix-rc' ) }}
|
||||
run: |
|
||||
$publisherPath = "$($env:GITHUB_WORKSPACE)\store\google\Publisher\bin\Release\net8.0\Publisher.dll"
|
||||
$credsPath = "$($HOME)\secrets\play_creds.json"
|
||||
$aabPath = "$($env:GITHUB_WORKSPACE)\com.x8bit.bitwarden.aab"
|
||||
$track = "internal"
|
||||
PUBLISHER_PATH="$GITHUB_WORKSPACE/store/google/Publisher/bin/Release/net7.0/Publisher.dll"
|
||||
CREDS_PATH="$HOME/secrets/play_creds.json"
|
||||
AAB_PATH="$GITHUB_WORKSPACE/com.x8bit.bitwarden.aab"
|
||||
TRACK="internal"
|
||||
|
||||
dotnet $publisherPath $credsPath $aabPath $track
|
||||
dotnet $PUBLISHER_PATH $CREDS_PATH $AAB_PATH $TRACK
|
||||
shell: bash
|
||||
|
||||
|
||||
f-droid:
|
||||
name: F-Droid Build
|
||||
runs-on: windows-2022
|
||||
env:
|
||||
android_folder_path: src\App\Platforms\Android
|
||||
android_folder_path_bash: src/App/Platforms/Android
|
||||
android_folder_path: src/App/Platforms/Android
|
||||
android_manifest_path: src/App/Platforms/Android/AndroidManifest.xml
|
||||
steps:
|
||||
- name: Setup NuGet
|
||||
@@ -305,14 +305,14 @@ jobs:
|
||||
nuget-version: 6.4.0
|
||||
|
||||
- name: Set up .NET
|
||||
uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0
|
||||
uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3.2.0
|
||||
with:
|
||||
dotnet-version: '8.0.x'
|
||||
|
||||
- name: Set up MSBuild
|
||||
uses: microsoft/setup-msbuild@ede762b26a2de8d110bb5a3db4d7e0e080c0e917 # v1.3.3
|
||||
|
||||
# This step might be obsolete at some point as .NET MAUI workloads
|
||||
# This step might be obsolete at some point as .NET MAUI workloads
|
||||
# are starting to come pre-installed on the GH Actions build agents.
|
||||
- name: Install MAUI Workload
|
||||
run: dotnet workload install maui --ignore-failed-sources
|
||||
@@ -337,25 +337,23 @@ jobs:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
|
||||
- name: Login to Azure - CI Subscription
|
||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||
|
||||
- name: Download secrets
|
||||
- name: Decrypt secrets
|
||||
env:
|
||||
ACCOUNT_NAME: bitwardenci
|
||||
CONTAINER_NAME: mobile
|
||||
FILE: app_fdroid-keystore.jks
|
||||
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }}
|
||||
run: |
|
||||
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME --name $FILE \
|
||||
--file ${{ env.android_folder_path_bash }}/$FILE --output none
|
||||
mkdir -p ~/secrets
|
||||
|
||||
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||
--output ./${{ env.main_app_folder_path }}/app_fdroid-keystore.jks ./.github/secrets/app_fdroid-keystore.jks.gpg
|
||||
shell: bash
|
||||
|
||||
- name: Increment version
|
||||
run: |
|
||||
BUILD_NUMBER=$((3000 + $GITHUB_RUN_NUMBER))
|
||||
echo "##### Setting F-Droid Version Code to $BUILD_NUMBER" | tee -a $GITHUB_STEP_SUMMARY
|
||||
|
||||
echo "########################################"
|
||||
echo "##### Setting Version Code $BUILD_NUMBER"
|
||||
echo "########################################"
|
||||
|
||||
sed -i "s/android:versionCode=\"1\"/android:versionCode=\"$BUILD_NUMBER\"/" \
|
||||
./${{ env.android_manifest_path }}
|
||||
@@ -363,16 +361,21 @@ jobs:
|
||||
|
||||
- name: Clean for F-Droid
|
||||
run: |
|
||||
$directoryBuildProps = $($env:GITHUB_WORKSPACE + "/Directory.Build.props");
|
||||
$appPath = $($env:GITHUB_WORKSPACE + "/${{ env.main_app_project_path }}");
|
||||
$corePath = $($env:GITHUB_WORKSPACE + "/src/Core/Core.csproj");
|
||||
|
||||
$androidManifest = $($env:GITHUB_WORKSPACE + "/${{ env.android_manifest_path }}");
|
||||
|
||||
Write-Output "##### Back up project files"
|
||||
Write-Output "########################################"
|
||||
Write-Output "##### Backup project files"
|
||||
Write-Output "########################################"
|
||||
|
||||
Copy-Item $androidManifest $($androidManifest + ".original");
|
||||
Copy-Item $directoryBuildProps $($directoryBuildProps + ".original");
|
||||
Copy-Item $appPath $($appPath + ".original");
|
||||
|
||||
Write-Output "########################################"
|
||||
Write-Output "##### Cleanup Android Manifest"
|
||||
Write-Output "########################################"
|
||||
|
||||
$xml=New-Object XML;
|
||||
$xml.Load($androidManifest);
|
||||
@@ -382,39 +385,44 @@ jobs:
|
||||
|
||||
$xml.Save($androidManifest);
|
||||
|
||||
Write-Output "##### Enabling FDROID constant"
|
||||
|
||||
(Get-Content $directoryBuildProps).Replace('<!-- <CustomConstants>FDROID</CustomConstants> -->', '<CustomConstants>FDROID</CustomConstants>') | Set-Content $directoryBuildProps
|
||||
|
||||
- name: Restore packages
|
||||
run: dotnet restore
|
||||
|
||||
- name: Build & Sign F-Droid
|
||||
- name: Build for F-Droid
|
||||
run: |
|
||||
$configuration = "Release";
|
||||
$projToBuild = $($env:GITHUB_WORKSPACE + "/${{ env.main_app_project_path }}");
|
||||
|
||||
Write-Output "########################################"
|
||||
Write-Output "##### Build $configuration FDROID
|
||||
Write-Output "########################################"
|
||||
|
||||
dotnet build $projToBuild -c $configuration -f ${{ env.target-net-version }}-android /p:CustomConstants="FDROID"
|
||||
|
||||
- name: Sign for F-Droid
|
||||
env:
|
||||
FDROID_KEYSTORE_PASSWORD: ${{ secrets.FDROID_KEYSTORE_PASSWORD }}
|
||||
run: |
|
||||
$projToBuild = "$($env:GITHUB_WORKSPACE)\${{ env.main_app_project_path }}";
|
||||
$projToBuild = $($env:GITHUB_WORKSPACE + "/${{ env.main_app_project_path }}");
|
||||
$packageName = "com.x8bit.bitwarden";
|
||||
|
||||
Write-Output "########################################"
|
||||
Write-Output "##### Sign FDroid"
|
||||
Write-Output "########################################"
|
||||
|
||||
$signingFdroidKeyStore = "$($env:GITHUB_WORKSPACE)\${{ env.android_folder_path }}\app_fdroid-keystore.jks"
|
||||
dotnet build $projToBuild -c Release -f ${{ env.target-net-version }}-android `
|
||||
/p:AndroidKeyStore=true `
|
||||
/p:AndroidSigningKeyStore=$signingFdroidKeyStore `
|
||||
/p:AndroidSigningKeyAlias=bitwarden `
|
||||
/p:AndroidSigningKeyPass="$($env:FDROID_KEYSTORE_PASSWORD)" `
|
||||
/p:AndroidSigningStorePass="$($env:FDROID_KEYSTORE_PASSWORD)" ` --no-restore
|
||||
dotnet publish $projToBuild -c Release -f ${{ env.target-net-version }}-android /p:AndroidKeyStore=true /p:AndroidSigningKeyStore=$("app_fdroid-keystore.jks") /p:AndroidSigningKeyAlias=bitwarden /p:AndroidSigningKeyPass="$($env:FDROID_KEYSTORE_PASSWORD)" /p:AndroidSigningStorePass="$($env:FDROID_KEYSTORE_PASSWORD)" /p:CustomConstants="FDROID" --no-restore
|
||||
|
||||
Write-Output "########################################"
|
||||
Write-Output "##### Copy FDroid apk to project root"
|
||||
Write-Output "########################################"
|
||||
|
||||
$signedApkPath = "$($env:GITHUB_WORKSPACE)\${{ env.main_app_folder_path }}\bin\Release\${{ env.target-net-version }}-android\$($packageName)-Signed.apk";
|
||||
$signedApkDestPath = "$($env:GITHUB_WORKSPACE)\com.x8bit.bitwarden-fdroid.apk";
|
||||
$signedApkPath = $($env:GITHUB_WORKSPACE + "/${{ env.main_app_folder_path }}/bin/Release/${{ env.target-net-version }}-android/publish/$($packageName)-Signed.apk");
|
||||
$signedApkDestPath = $($env:GITHUB_WORKSPACE + "/com.x8bit.bitwarden-fdroid.apk");
|
||||
|
||||
Copy-Item $signedApkPath $signedApkDestPath
|
||||
|
||||
- name: Upload F-Droid .apk artifact
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
|
||||
with:
|
||||
name: com.x8bit.bitwarden-fdroid.apk
|
||||
path: ./com.x8bit.bitwarden-fdroid.apk
|
||||
@@ -426,13 +434,12 @@ jobs:
|
||||
-t sha256 | Out-File -Encoding ASCII ./bw-fdroid-apk-sha256.txt
|
||||
|
||||
- name: Upload F-Droid sha file
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
|
||||
with:
|
||||
name: bw-fdroid-apk-sha256.txt
|
||||
path: ./bw-fdroid-apk-sha256.txt
|
||||
if-no-files-found: error
|
||||
|
||||
|
||||
ios:
|
||||
name: Apple iOS
|
||||
runs-on: macos-13
|
||||
@@ -451,13 +458,13 @@ jobs:
|
||||
uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0
|
||||
with:
|
||||
nuget-version: 6.4.0
|
||||
|
||||
|
||||
- name: Set up .NET
|
||||
uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0
|
||||
uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3.2.0
|
||||
with:
|
||||
dotnet-version: '8.0.x'
|
||||
|
||||
# This step might be obsolete at some point as .NET MAUI workloads
|
||||
|
||||
# This step might be obsolete at some point as .NET MAUI workloads
|
||||
# are starting to come pre-installed on the GH Actions build agents.
|
||||
- name: Install MAUI Workload
|
||||
run: dotnet workload install maui --ignore-failed-sources
|
||||
@@ -486,71 +493,73 @@ jobs:
|
||||
keyvault: "bitwarden-ci"
|
||||
secrets: "appcenter-ios-token"
|
||||
|
||||
- name: Download Provisioning Profiles secrets
|
||||
- name: Decrypt secrets
|
||||
env:
|
||||
ACCOUNT_NAME: bitwardenci
|
||||
CONTAINER_NAME: profiles
|
||||
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }}
|
||||
run: |
|
||||
mkdir -p $HOME/secrets
|
||||
profiles=(
|
||||
"dist_autofill.mobileprovision"
|
||||
"dist_bitwarden.mobileprovision"
|
||||
"dist_extension.mobileprovision"
|
||||
"dist_share_extension.mobileprovision"
|
||||
"dist_bitwarden_watch_app.mobileprovision"
|
||||
"dist_bitwarden_watch_app_extension.mobileprovision"
|
||||
)
|
||||
mkdir -p ~/secrets
|
||||
|
||||
for FILE in "${profiles[@]}"
|
||||
do
|
||||
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME --name $FILE \
|
||||
--file $HOME/secrets/$FILE --output none
|
||||
done
|
||||
|
||||
- name: Download Google Services secret
|
||||
env:
|
||||
ACCOUNT_NAME: bitwardenci
|
||||
CONTAINER_NAME: mobile
|
||||
FILE: GoogleService-Info.plist
|
||||
run: |
|
||||
mkdir -p $HOME/secrets
|
||||
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME --name $FILE \
|
||||
--file src/watchOS/bitwarden/$FILE --output none
|
||||
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||
--output $HOME/secrets/bitwarden-mobile-key.p12 ./.github/secrets/bitwarden-mobile-key.p12.gpg
|
||||
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||
--output $HOME/secrets/iphone-distribution-cert.p12 ./.github/secrets/iphone-distribution-cert.p12.gpg
|
||||
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||
--output $HOME/secrets/dist_autofill.mobileprovision ./.github/secrets/dist_autofill.mobileprovision.gpg
|
||||
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||
--output $HOME/secrets/dist_bitwarden.mobileprovision ./.github/secrets/dist_bitwarden.mobileprovision.gpg
|
||||
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||
--output $HOME/secrets/dist_extension.mobileprovision ./.github/secrets/dist_extension.mobileprovision.gpg
|
||||
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||
--output $HOME/secrets/dist_share_extension.mobileprovision \
|
||||
./.github/secrets/dist_share_extension.mobileprovision.gpg
|
||||
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||
--output $HOME/secrets/dist_watch_app.mobileprovision \
|
||||
./.github/secrets/dist_watch_app.mobileprovision.gpg
|
||||
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||
--output $HOME/secrets/dist_watch_app_extension.mobileprovision \
|
||||
./.github/secrets/dist_watch_app_extension.mobileprovision.gpg
|
||||
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||
--output ./src/watchOS/bitwarden/GoogleService-Info.plist ./.github/secrets/GoogleService-Info.plist.gpg
|
||||
|
||||
- name: Increment version
|
||||
run: |
|
||||
BUILD_NUMBER=$((100 + $GITHUB_RUN_NUMBER))
|
||||
echo "##### Setting iOS CFBundleVersion to $BUILD_NUMBER" | tee -a $GITHUB_STEP_SUMMARY
|
||||
|
||||
echo "########################################"
|
||||
echo "##### Setting CFBundleVersion $BUILD_NUMBER"
|
||||
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>/' ./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.ShareExtension/Info.plist
|
||||
cd src/watchOS/bitwarden
|
||||
agvtool new-version -all $BUILD_NUMBER
|
||||
agvtool new-version -all $BUILD_NUMBER
|
||||
|
||||
- name: Update Entitlements
|
||||
run: |
|
||||
echo "########################################"
|
||||
echo "##### Updating Entitlements"
|
||||
echo "########################################"
|
||||
|
||||
perl -0777 -pi.bak -e 's/<key>aps-environment<\/key>\s*<string>development<\/string>/<key>aps-environment<\/key>\n\t<string>production<\/string>/' ./${{ env.ios_folder_path }}/Entitlements.plist
|
||||
|
||||
- name: Get certificates
|
||||
run: |
|
||||
mkdir -p $HOME/certificates
|
||||
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/ios-distribution |
|
||||
jq -r .value | base64 -d > $HOME/certificates/ios-distribution.p12
|
||||
|
||||
|
||||
- name: Set up Keychain
|
||||
env:
|
||||
KEYCHAIN_PASSWORD: ${{ secrets.IOS_KEYCHAIN_PASSWORD }}
|
||||
MOBILE_KEY_PASSWORD: ${{ secrets.IOS_KEY_PASSWORD }}
|
||||
DIST_CERT_PASSWORD: ${{ secrets.IOS_DIST_CERT_PASSWORD }}
|
||||
run: |
|
||||
security create-keychain -p $KEYCHAIN_PASSWORD build.keychain
|
||||
security default-keychain -s build.keychain
|
||||
security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain
|
||||
security set-keychain-settings -lut 1200 build.keychain
|
||||
|
||||
security import $HOME/certificates/ios-distribution.p12 -k build.keychain -P "" -T /usr/bin/codesign \
|
||||
-T /usr/bin/security
|
||||
security import ~/secrets/bitwarden-mobile-key.p12 -k build.keychain -P $MOBILE_KEY_PASSWORD \
|
||||
-T /usr/bin/codesign -T /usr/bin/security
|
||||
security import ~/secrets/iphone-distribution-cert.p12 -k build.keychain -P $DIST_CERT_PASSWORD \
|
||||
-T /usr/bin/codesign -T /usr/bin/security
|
||||
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain
|
||||
|
||||
- name: Set up provisioning profiles
|
||||
@@ -559,8 +568,8 @@ jobs:
|
||||
BITWARDEN_PROFILE_PATH=$HOME/secrets/dist_bitwarden.mobileprovision
|
||||
EXTENSION_PROFILE_PATH=$HOME/secrets/dist_extension.mobileprovision
|
||||
SHARE_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_share_extension.mobileprovision
|
||||
WATCH_APP_PROFILE_PATH=$HOME/secrets/dist_bitwarden_watch_app.mobileprovision
|
||||
WATCH_APP_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_bitwarden_watch_app_extension.mobileprovision
|
||||
WATCH_APP_PROFILE_PATH=$HOME/secrets/dist_watch_app.mobileprovision
|
||||
WATCH_APP_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_watch_app_extension.mobileprovision
|
||||
PROFILES_DIR_PATH=$HOME/Library/MobileDevice/Provisioning\ Profiles
|
||||
|
||||
mkdir -p "$PROFILES_DIR_PATH"
|
||||
@@ -588,50 +597,74 @@ jobs:
|
||||
|
||||
- name: Bulid WatchApp
|
||||
run: |
|
||||
echo "########################################"
|
||||
echo "##### Build WatchApp with Release Configuration"
|
||||
echo "########################################"
|
||||
|
||||
xcodebuild archive -workspace ./src/watchOS/bitwarden/bitwarden.xcodeproj/project.xcworkspace -configuration Release -scheme bitwarden\ WatchKit\ App -archivePath ./src/watchOS/bitwarden
|
||||
|
||||
echo "########################################"
|
||||
echo "##### Done"
|
||||
echo "########################################"
|
||||
|
||||
- name: Archive Build for App Store
|
||||
run: |
|
||||
echo "##### Archive for Release ios-arm64"
|
||||
Write-Output "########################################"
|
||||
Write-Output "##### Archive for Release ios-arm64
|
||||
Write-Output "########################################"
|
||||
|
||||
dotnet publish ${{ env.main_app_project_path }} -c Release -f ${{ env.target-net-version }}-ios /p:RuntimeIdentifier=ios-arm64 /p:ArchiveOnBuild=true /p:MtouchUseLlvm=false
|
||||
|
||||
Write-Output "########################################"
|
||||
Write-Output "##### Done"
|
||||
Write-Output "########################################"
|
||||
shell: pwsh
|
||||
|
||||
- name: Archive Build for Mobile Automation
|
||||
run: |
|
||||
echo "##### Archive Debug for iossimulator-x64"
|
||||
Write-Output "########################################"
|
||||
Write-Output "##### Archive Debug for iossimulator-x64
|
||||
Write-Output "########################################"
|
||||
|
||||
dotnet build ${{ env.main_app_project_path }} -c Debug -f ${{ env.target-net-version }}-ios /p:RuntimeIdentifier=iossimulator-x64 /p:ArchiveOnBuild=true /p:MtouchUseLlvm=false
|
||||
ls $HOME/Library/Developer/Xcode/Archives
|
||||
|
||||
Write-Output "########################################"
|
||||
Write-Output "##### Done"
|
||||
Write-Output "########################################"
|
||||
ls ~/Library/Developer/Xcode/Archives
|
||||
shell: pwsh
|
||||
|
||||
- name: Export .ipa for App Store
|
||||
env:
|
||||
EXPORT_OPTIONS_PATH: ./.github/resources/export-options-app-store.plist
|
||||
EXPORT_PATH: ./bitwarden-export
|
||||
run: |
|
||||
EXPORT_OPTIONS_PATH="./.github/resources/export-options-app-store.plist"
|
||||
ARCHIVE_PATH="$HOME/Library/Developer/Xcode/Archives/*/*.xcarchive"
|
||||
EXPORT_PATH="./bitwarden-export"
|
||||
|
||||
xcodebuild -exportArchive -archivePath $ARCHIVE_PATH -exportPath $EXPORT_PATH \
|
||||
-exportOptionsPlist $EXPORT_OPTIONS_PATH
|
||||
|
||||
- name: Export .app for Automation CI
|
||||
env:
|
||||
ARCHIVE_PATH: ./${{ env.main_app_folder_path }}/bin/Debug/${{ env.target-net-version }}-ios/iossimulator-x64
|
||||
EXPORT_PATH: ./bitwarden-export
|
||||
run: |
|
||||
ARCHIVE_PATH="./${{ env.main_app_folder_path }}/bin/Debug/${{ env.target-net-version }}-ios/iossimulator-x64"
|
||||
EXPORT_PATH="./bitwarden-export"
|
||||
|
||||
zip -r -q ${{ env.app_ci_output_filename }}.app.zip $ARCHIVE_PATH
|
||||
mv ${{ env.app_ci_output_filename }}.app.zip $EXPORT_PATH
|
||||
|
||||
- name: Copy all dSYMs files to upload
|
||||
env:
|
||||
EXPORT_PATH: ./bitwarden-export
|
||||
WATCH_ARCHIVE_DSYMS_PATH: ./src/watchOS/bitwarden.xcarchive/dSYMs/
|
||||
WATCH_DSYMS_EXPORT_PATH: ./bitwarden-export/Watch_dSYMs
|
||||
run: |
|
||||
ARCHIVE_DSYMS_PATH="$HOME/Library/Developer/Xcode/Archives/*/*.xcarchive/dSYMs"
|
||||
EXPORT_PATH="./bitwarden-export"
|
||||
|
||||
WATCH_ARCHIVE_DSYMS_PATH="./src/watchOS/bitwarden.xcarchive/dSYMs/"
|
||||
WATCH_DSYMS_EXPORT_PATH="$EXPORT_PATH/Watch_dSYMs"
|
||||
|
||||
cp -r -v $ARCHIVE_DSYMS_PATH $EXPORT_PATH
|
||||
mkdir $WATCH_DSYMS_EXPORT_PATH
|
||||
cp -r -v $WATCH_ARCHIVE_DSYMS_PATH $WATCH_DSYMS_EXPORT_PATH
|
||||
|
||||
- name: Upload App Store .ipa & dSYMs artifacts
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
|
||||
with:
|
||||
name: Bitwarden iOS
|
||||
path: |
|
||||
@@ -640,7 +673,7 @@ jobs:
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload .app file for Automation CI
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
|
||||
with:
|
||||
name: ${{ env.app_ci_output_filename }}.app.zip
|
||||
path: ./bitwarden-export/${{ env.app_ci_output_filename }}.app.zip
|
||||
@@ -674,7 +707,10 @@ jobs:
|
||||
|| (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0)
|
||||
|| github.ref == 'refs/heads/hotfix-rc'
|
||||
run: |
|
||||
echo "########################################"
|
||||
echo "##### Uploading Watch dSYMs to Firebase"
|
||||
echo "########################################"
|
||||
|
||||
find "$HOME/Library/Developer/XCode/DerivedData" -name "upload-symbols" -exec chmod +x {} \; -exec {} -gsp "./src/watchOS/bitwarden/GoogleService-Info.plist" -p ios "./bitwarden-export/Watch_dSYMs" \;
|
||||
|
||||
- name: Validate app in App Store
|
||||
@@ -690,6 +726,7 @@ jobs:
|
||||
run: |
|
||||
xcrun altool --validate-app --type ios --file "./bitwarden-export/Bitwarden.ipa" \
|
||||
--username "$APPLE_ID_USERNAME" --password "$APPLE_ID_PASSWORD"
|
||||
shell: bash
|
||||
|
||||
- name: Deploy to App Store
|
||||
if: |
|
||||
@@ -733,13 +770,13 @@ jobs:
|
||||
secrets: "crowdin-api-token"
|
||||
|
||||
- name: Upload Sources
|
||||
uses: crowdin/github-action@c953b17499daa6be3e5afbf7a63616fb02d8b18d # v1.19.0
|
||||
uses: crowdin/github-action@97bef4fd3f1b853eb105bc99b8d0d563760e024c # v1.17.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
|
||||
with:
|
||||
config: crowdin.yml
|
||||
crowdin_branch_name: main
|
||||
crowdin_branch_name: main
|
||||
upload_sources: true
|
||||
upload_translations: false
|
||||
|
||||
@@ -757,11 +794,27 @@ jobs:
|
||||
steps:
|
||||
- name: Check if any job failed
|
||||
if: |
|
||||
(github.ref == 'refs/heads/main'
|
||||
|| github.ref == 'refs/heads/rc'
|
||||
|| github.ref == 'refs/heads/hotfix-rc')
|
||||
&& contains(needs.*.result, 'failure')
|
||||
run: exit 1
|
||||
(github.ref == 'refs/heads/main')
|
||||
|| (github.ref == 'refs/heads/rc')
|
||||
|| (github.ref == 'refs/heads/hotfix-rc')
|
||||
env:
|
||||
CLOC_STATUS: ${{ needs.cloc.result }}
|
||||
ANDROID_STATUS: ${{ needs.android.result }}
|
||||
F_DROID_STATUS: ${{ needs.f-droid.result }}
|
||||
IOS_STATUS: ${{ needs.ios.result }}
|
||||
CROWDIN_PUSH_STATUS: ${{ needs.crowdin-push.result }}
|
||||
run: |
|
||||
if [ "$CLOC_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
elif [ "$ANDROID_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
elif [ "$F_DROID_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
elif [ "$IOS_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
elif [ "$CROWDIN_PUSH_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Login to Azure - CI Subscription
|
||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||
|
||||
53
.github/workflows/cleanup-rc-branch.yml
vendored
53
.github/workflows/cleanup-rc-branch.yml
vendored
@@ -1,53 +0,0 @@
|
||||
---
|
||||
name: Cleanup RC Branch
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v**
|
||||
|
||||
jobs:
|
||||
delete-rc:
|
||||
name: Delete RC Branch
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Login to Azure - CI Subscription
|
||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||
|
||||
- name: Retrieve bot secrets
|
||||
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: Checkout main
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
ref: main
|
||||
token: ${{ steps.retrieve-bot-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
|
||||
|
||||
- name: Check if a RC branch exists
|
||||
id: branch-check
|
||||
run: |
|
||||
hotfix_rc_branch_check=$(git ls-remote --heads origin hotfix-rc | wc -l)
|
||||
rc_branch_check=$(git ls-remote --heads origin rc | wc -l)
|
||||
|
||||
if [[ "${hotfix_rc_branch_check}" -gt 0 ]]; then
|
||||
echo "hotfix-rc branch exists." | tee -a $GITHUB_STEP_SUMMARY
|
||||
echo "name=hotfix-rc" >> $GITHUB_OUTPUT
|
||||
elif [[ "${rc_branch_check}" -gt 0 ]]; then
|
||||
echo "rc branch exists." | tee -a $GITHUB_STEP_SUMMARY
|
||||
echo "name=rc" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Delete RC branch
|
||||
env:
|
||||
BRANCH_NAME: ${{ steps.branch-check.outputs.name }}
|
||||
run: |
|
||||
if ! [[ -z "$BRANCH_NAME" ]]; then
|
||||
git push --quiet origin --delete $BRANCH_NAME
|
||||
echo "Deleted $BRANCH_NAME branch." | tee -a $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
4
.github/workflows/crowdin-pull.yml
vendored
4
.github/workflows/crowdin-pull.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
_CROWDIN_PROJECT_ID: "269690"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
|
||||
- name: Login to Azure - CI Subscription
|
||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase"
|
||||
|
||||
- name: Download translations
|
||||
uses: crowdin/github-action@c953b17499daa6be3e5afbf7a63616fb02d8b18d # v1.19.0
|
||||
uses: crowdin/github-action@97bef4fd3f1b853eb105bc99b8d0d563760e024c # v1.17.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
|
||||
|
||||
2
.github/workflows/pr-labeler.yml
vendored
2
.github/workflows/pr-labeler.yml
vendored
@@ -12,6 +12,6 @@ jobs:
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5.0.0
|
||||
- uses: actions/labeler@ac9175f8a1f3625fd0d4fb234536d26811351594 # v4.3.0
|
||||
with:
|
||||
sync-labels: true
|
||||
|
||||
62
.github/workflows/release.yml
vendored
62
.github/workflows/release.yml
vendored
@@ -28,7 +28,7 @@ jobs:
|
||||
branch-name: ${{ steps.branch.outputs.branch-name }}
|
||||
steps:
|
||||
- name: Branch check
|
||||
if: inputs.release_type != 'Dry Run'
|
||||
if: github.event.inputs.release_type != 'Dry Run'
|
||||
run: |
|
||||
if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then
|
||||
echo "==================================="
|
||||
@@ -38,15 +38,15 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
|
||||
- name: Check Release Version
|
||||
id: version
|
||||
uses: bitwarden/gh-actions/release-version-check@main
|
||||
with:
|
||||
release-type: ${{ inputs.release_type }}
|
||||
release-type: ${{ github.event.inputs.release_type }}
|
||||
project-type: xamarin
|
||||
file: src/App/Platforms/Android/AndroidManifest.xml
|
||||
file: src/Android/Properties/AndroidManifest.xml
|
||||
|
||||
- name: Get branch name
|
||||
id: branch
|
||||
@@ -55,8 +55,8 @@ jobs:
|
||||
echo "branch-name=$BRANCH_NAME" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Create GitHub deployment
|
||||
if: ${{ inputs.release_type != 'Dry Run' }}
|
||||
uses: chrnorm/deployment-action@55729fcebec3d284f60f5bcabbd8376437d696b1 # v2.0.7
|
||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||
uses: chrnorm/deployment-action@d42cde7132fcec920de534fffc3be83794335c00 # v2.0.5
|
||||
id: deployment
|
||||
with:
|
||||
token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
@@ -67,16 +67,16 @@ jobs:
|
||||
|
||||
|
||||
- name: Download all artifacts
|
||||
if: ${{ inputs.release_type != 'Dry Run' }}
|
||||
uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
|
||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||
uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d # v3.0.0
|
||||
with:
|
||||
workflow: build.yml
|
||||
workflow_conclusion: success
|
||||
branch: ${{ steps.branch.outputs.branch-name }}
|
||||
|
||||
- name: Dry Run - Download all artifacts
|
||||
if: ${{ inputs.release_type == 'Dry Run' }}
|
||||
uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
|
||||
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
||||
uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d # v3.0.0
|
||||
with:
|
||||
workflow: build.yml
|
||||
workflow_conclusion: success
|
||||
@@ -86,8 +86,8 @@ jobs:
|
||||
run: zip -r Bitwarden\ iOS.zip Bitwarden\ iOS
|
||||
|
||||
- name: Create release
|
||||
if: ${{ inputs.release_type != 'Dry Run' }}
|
||||
uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0
|
||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||
uses: ncipollo/release-action@6c75be85e571768fa31b40abf38de58ba0397db5 # v1.13.0
|
||||
with:
|
||||
artifacts: "./com.x8bit.bitwarden.aab/com.x8bit.bitwarden.aab,
|
||||
./com.x8bit.bitwarden.apk/com.x8bit.bitwarden.apk,
|
||||
@@ -103,16 +103,16 @@ jobs:
|
||||
draft: true
|
||||
|
||||
- name: Update deployment status to Success
|
||||
if: ${{ inputs.release_type != 'Dry Run' && success() }}
|
||||
uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
|
||||
if: ${{ github.event.inputs.release_type != 'Dry Run' && success() }}
|
||||
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1
|
||||
with:
|
||||
token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
state: 'success'
|
||||
deployment-id: ${{ steps.deployment.outputs.deployment_id }}
|
||||
|
||||
- name: Update deployment status to Failure
|
||||
if: ${{ inputs.release_type != 'Dry Run' && failure() }}
|
||||
uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
|
||||
if: ${{ github.event.inputs.release_type != 'Dry Run' && failure() }}
|
||||
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1
|
||||
with:
|
||||
token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
state: 'failure'
|
||||
@@ -126,11 +126,11 @@ jobs:
|
||||
if: inputs.fdroid_publish
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
|
||||
- name: Download F-Droid .apk artifact
|
||||
if: ${{ inputs.release_type != 'Dry Run' }}
|
||||
uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
|
||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||
uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d # v3.0.0
|
||||
with:
|
||||
workflow: build.yml
|
||||
workflow_conclusion: success
|
||||
@@ -138,8 +138,8 @@ jobs:
|
||||
name: com.x8bit.bitwarden-fdroid.apk
|
||||
|
||||
- name: Dry Run - Download F-Droid .apk artifact
|
||||
if: ${{ inputs.release_type == 'Dry Run' }}
|
||||
uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
|
||||
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
||||
uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d # v3.0.0
|
||||
with:
|
||||
workflow: build.yml
|
||||
workflow_conclusion: success
|
||||
@@ -147,7 +147,7 @@ jobs:
|
||||
name: com.x8bit.bitwarden-fdroid.apk
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
|
||||
with:
|
||||
node-version: '16.x'
|
||||
|
||||
@@ -176,19 +176,13 @@ jobs:
|
||||
- name: Install Node dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Login to Azure - CI Subscription
|
||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||
|
||||
- name: Download secrets
|
||||
- name: Decrypt secrets
|
||||
env:
|
||||
ACCOUNT_NAME: bitwardenci
|
||||
CONTAINER_NAME: mobile
|
||||
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }}
|
||||
run: |
|
||||
mkdir -p $HOME/secrets
|
||||
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
|
||||
--name store_fdroid-keystore.jks --file ./store/fdroid/keystore.jks --output none
|
||||
mkdir -p ~/secrets
|
||||
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||
--output ./store/fdroid/keystore.jks ./.github/secrets/store_fdroid-keystore.jks.gpg
|
||||
|
||||
- name: Compile for F-Droid Store
|
||||
env:
|
||||
@@ -217,5 +211,5 @@ jobs:
|
||||
cd $GITHUB_WORKSPACE
|
||||
|
||||
- name: Deploy to gh-pages
|
||||
if: ${{ inputs.release_type != 'Dry Run' }}
|
||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||
run: npm run deploy
|
||||
|
||||
24
.github/workflows/version-auto-bump.yml
vendored
24
.github/workflows/version-auto-bump.yml
vendored
@@ -11,6 +11,24 @@ jobs:
|
||||
name: Bump Mobile Version
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout Branch
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
|
||||
- name: Calculate bumped version
|
||||
id: version
|
||||
env:
|
||||
RELEASE_TAG: ${{ github.ref }}
|
||||
run: |
|
||||
CURR_MAJOR=$(echo $RELEASE_TAG | sed -r 's/refs\/tags\/v([0-9]{4}\.[0-9]{1,2})\.([0-9]{1,2})/\1/')
|
||||
CURR_PATCH=$(echo $RELEASE_TAG | sed -r 's/refs\/tags\/v([0-9]{4}\.[0-9]{1,2})\.([0-9]{1,2})/\2/')
|
||||
echo "Current Major: $CURR_MAJOR"
|
||||
echo "Current Patch: $CURR_PATCH"
|
||||
|
||||
NEW_PATCH=$((CURR_PATCH+1))
|
||||
NEW_VER=$CURR_MAJOR.$NEW_PATCH
|
||||
echo "New Version: $NEW_VER"
|
||||
echo "new_version=$NEW_VER" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Login to Azure - CI Subscription
|
||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||
with:
|
||||
@@ -23,9 +41,9 @@ jobs:
|
||||
keyvault: bitwarden-ci
|
||||
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
|
||||
|
||||
- name: Trigger Version Bump workflow
|
||||
- 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"}' | \
|
||||
gh workflow run version-bump.yml --json --repo bitwarden/mobile
|
||||
echo '{"cut_rc_branch": "false", "version_number": "${{ steps.version.outputs.new_version }}"}' | \
|
||||
gh workflow run version-bump.yml --json --repo bitwarden/mobile
|
||||
176
.github/workflows/version-bump.yml
vendored
176
.github/workflows/version-bump.yml
vendored
@@ -1,13 +1,13 @@
|
||||
---
|
||||
name: Version Bump
|
||||
run-name: Version Bump - v${{ inputs.version_number }}
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version_number_override:
|
||||
description: "New version override (leave blank for automatic calculation, example: '2024.1.0')"
|
||||
required: false
|
||||
type: string
|
||||
version_number:
|
||||
description: "New version (example: '2024.1.0')"
|
||||
required: true
|
||||
cut_rc_branch:
|
||||
description: "Cut RC branch?"
|
||||
default: true
|
||||
@@ -15,16 +15,22 @@ on:
|
||||
|
||||
jobs:
|
||||
bump_version:
|
||||
name: Bump Version
|
||||
name: "Bump Version to v${{ inputs.version_number }}"
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
version: ${{ steps.set-final-version-output.outputs.version }}
|
||||
steps:
|
||||
- name: Validate version input
|
||||
if: ${{ inputs.version_number_override != '' }}
|
||||
uses: bitwarden/gh-actions/version-check@main
|
||||
- name: Login to Azure - CI Subscription
|
||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||
with:
|
||||
version: ${{ inputs.version_number_override }}
|
||||
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||
|
||||
- name: Retrieve secrets
|
||||
id: retrieve-secrets
|
||||
uses: bitwarden/gh-actions/get-keyvault-secrets@main
|
||||
with:
|
||||
keyvault: "bitwarden-ci"
|
||||
secrets: "github-gpg-private-key,
|
||||
github-gpg-private-key-passphrase,
|
||||
github-pat-bitwarden-devops-bot-repo-scope"
|
||||
|
||||
- name: Checkout Branch
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
@@ -41,20 +47,6 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Login to Azure - CI Subscription
|
||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
||||
|
||||
- name: Retrieve secrets
|
||||
id: retrieve-secrets
|
||||
uses: bitwarden/gh-actions/get-keyvault-secrets@main
|
||||
with:
|
||||
keyvault: "bitwarden-ci"
|
||||
secrets: "github-gpg-private-key,
|
||||
github-gpg-private-key-passphrase,
|
||||
github-pat-bitwarden-devops-bot-repo-scope"
|
||||
|
||||
- name: Import GPG key
|
||||
uses: crazy-max/ghaction-import-gpg@01dd5d3ca463c7f10f7f4f7b4f177225ac661ee4 # v6.1.0
|
||||
with:
|
||||
@@ -63,38 +55,25 @@ jobs:
|
||||
git_user_signingkey: true
|
||||
git_commit_gpgsign: true
|
||||
|
||||
- name: Setup git
|
||||
run: |
|
||||
git config --local user.email "106330231+bitwarden-devops-bot@users.noreply.github.com"
|
||||
git config --local user.name "bitwarden-devops-bot"
|
||||
|
||||
- name: Create Version Branch
|
||||
id: create-branch
|
||||
run: |
|
||||
NAME=version_bump_${{ github.ref_name }}_$(date +"%Y-%m-%d")
|
||||
NAME=version_bump_${{ github.ref_name }}_${{ inputs.version_number }}
|
||||
git switch -c $NAME
|
||||
echo "name=$NAME" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Install xmllint
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libxml2-utils
|
||||
|
||||
- name: Get current version
|
||||
id: current-version
|
||||
run: |
|
||||
CURRENT_VERSION=$(xmllint --xpath '
|
||||
string(/manifest/@*[local-name()="versionName"
|
||||
and namespace-uri()="http://schemas.android.com/apk/res/android"])
|
||||
' src/App/Platforms/Android/AndroidManifest.xml)
|
||||
echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
|
||||
run: sudo apt install -y libxml2-utils
|
||||
|
||||
- name: Verify input version
|
||||
if: ${{ inputs.version_number_override != '' }}
|
||||
env:
|
||||
CURRENT_VERSION: ${{ steps.current-version.outputs.version }}
|
||||
NEW_VERSION: ${{ inputs.version_number_override }}
|
||||
NEW_VERSION: ${{ inputs.version_number }}
|
||||
run: |
|
||||
CURRENT_VERSION=$(xmllint --xpath '
|
||||
string(/manifest/@*[local-name()="versionName"
|
||||
and namespace-uri()="http://schemas.android.com/apk/res/android"])
|
||||
' src/App/Platforms/Android/AndroidManifest.xml)
|
||||
|
||||
# Error if version has not changed.
|
||||
if [[ "$NEW_VERSION" == "$CURRENT_VERSION" ]]; then
|
||||
echo "Version has not changed."
|
||||
@@ -110,93 +89,40 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Calculate next release version
|
||||
if: ${{ inputs.version_number_override == '' }}
|
||||
id: calculate-next-version
|
||||
uses: bitwarden/gh-actions/version-next@main
|
||||
with:
|
||||
version: ${{ steps.current-version.outputs.version }}
|
||||
|
||||
- name: Bump Version - Android XML - Version Override
|
||||
if: ${{ inputs.version_number_override != '' }}
|
||||
id: bump-version-override
|
||||
- name: Bump Version - Android XML
|
||||
uses: bitwarden/gh-actions/version-bump@main
|
||||
with:
|
||||
version: ${{ inputs.version_number }}
|
||||
file_path: "src/App/Platforms/Android/AndroidManifest.xml"
|
||||
version: ${{ inputs.version_number_override }}
|
||||
|
||||
- name: Bump Version - Android XML - Automatic Calculation
|
||||
if: ${{ inputs.version_number_override == '' }}
|
||||
id: bump-version-automatic
|
||||
uses: bitwarden/gh-actions/version-bump@main
|
||||
with:
|
||||
file_path: "src/App/Platforms/Android/AndroidManifest.xml"
|
||||
version: ${{ steps.calculate-next-version.outputs.version }}
|
||||
|
||||
- name: Bump Version - iOS.Autofill - Version Override
|
||||
if: ${{ inputs.version_number_override != '' }}
|
||||
- name: Bump Version - iOS.Autofill
|
||||
uses: bitwarden/gh-actions/version-bump@main
|
||||
with:
|
||||
version: ${{ inputs.version_number }}
|
||||
file_path: "src/iOS.Autofill/Info.plist"
|
||||
version: ${{ inputs.version_number_override }}
|
||||
|
||||
- name: Bump Version - iOS.Autofill - Automatic Calculation
|
||||
if: ${{ inputs.version_number_override == '' }}
|
||||
uses: bitwarden/gh-actions/version-bump@main
|
||||
with:
|
||||
file_path: "src/iOS.Autofill/Info.plist"
|
||||
version: ${{ steps.calculate-next-version.outputs.version }}
|
||||
|
||||
- name: Bump Version - iOS.Extension - Version Override
|
||||
if: ${{ inputs.version_number_override != '' }}
|
||||
- name: Bump Version - iOS.Extension
|
||||
uses: bitwarden/gh-actions/version-bump@main
|
||||
with:
|
||||
version: ${{ inputs.version_number }}
|
||||
file_path: "src/iOS.Extension/Info.plist"
|
||||
version: ${{ inputs.version_number_override }}
|
||||
|
||||
- name: Bump Version - iOS.Extension - Automatic Calculation
|
||||
if: ${{ inputs.version_number_override == '' }}
|
||||
uses: bitwarden/gh-actions/version-bump@main
|
||||
with:
|
||||
file_path: "src/iOS.Extension/Info.plist"
|
||||
version: ${{ steps.calculate-next-version.outputs.version }}
|
||||
|
||||
- name: Bump Version - iOS.ShareExtension - Version Override
|
||||
if: ${{ inputs.version_number_override != '' }}
|
||||
- name: Bump Version - iOS.ShareExtension
|
||||
uses: bitwarden/gh-actions/version-bump@main
|
||||
with:
|
||||
version: ${{ inputs.version_number }}
|
||||
file_path: "src/iOS.ShareExtension/Info.plist"
|
||||
version: ${{ inputs.version_number_override }}
|
||||
|
||||
- name: Bump Version - iOS.ShareExtension - Automatic Calculation
|
||||
if: ${{ inputs.version_number_override == '' }}
|
||||
uses: bitwarden/gh-actions/version-bump@main
|
||||
with:
|
||||
file_path: "src/iOS.ShareExtension/Info.plist"
|
||||
version: ${{ steps.calculate-next-version.outputs.version }}
|
||||
|
||||
- name: Bump Version - iOS - Version Override
|
||||
if: ${{ inputs.version_number_override != '' }}
|
||||
- name: Bump Version - iOS
|
||||
uses: bitwarden/gh-actions/version-bump@main
|
||||
with:
|
||||
version: ${{ inputs.version_number }}
|
||||
file_path: "src/App/Platforms/iOS/Info.plist"
|
||||
version: ${{ inputs.version_number_override }}
|
||||
|
||||
- name: Bump Version - iOS - Automatic Calculation
|
||||
if: ${{ inputs.version_number_override == '' }}
|
||||
uses: bitwarden/gh-actions/version-bump@main
|
||||
with:
|
||||
file_path: "src/App/Platforms/iOS/Info.plist"
|
||||
version: ${{ steps.calculate-next-version.outputs.version }}
|
||||
|
||||
- name: Set Job output
|
||||
id: set-final-version-output
|
||||
- name: Setup git
|
||||
run: |
|
||||
if [[ "${{ steps.bump-version-override.outcome }}" == "success" ]]; then
|
||||
echo "version=${{ inputs.version_number_override }}" >> $GITHUB_OUTPUT
|
||||
elif [[ "${{ steps.bump-version-automatic.outcome }}" == "success" ]]; then
|
||||
echo "version=${{ steps.calculate-next-version.outputs.version }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
git config --local user.email "106330231+bitwarden-devops-bot@users.noreply.github.com"
|
||||
git config --local user.name "bitwarden-devops-bot"
|
||||
|
||||
- name: Check if version changed
|
||||
id: version-changed
|
||||
@@ -210,7 +136,7 @@ jobs:
|
||||
|
||||
- name: Commit files
|
||||
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
|
||||
run: git commit -m "Bumped version to ${{ steps.set-final-version-output.outputs.version }}" -a
|
||||
run: git commit -m "Bumped version to ${{ inputs.version_number }}" -a
|
||||
|
||||
- name: Push changes
|
||||
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
|
||||
@@ -224,7 +150,7 @@ jobs:
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
|
||||
PR_BRANCH: ${{ steps.create-branch.outputs.name }}
|
||||
TITLE: "Bump version to ${{ steps.set-final-version-output.outputs.version }}"
|
||||
TITLE: "Bump version to ${{ inputs.version_number }}"
|
||||
run: |
|
||||
PR_URL=$(gh pr create --title "$TITLE" \
|
||||
--base "main" \
|
||||
@@ -240,18 +166,16 @@ jobs:
|
||||
- [X] Other
|
||||
|
||||
## Objective
|
||||
Automated version bump to ${{ steps.set-final-version-output.outputs.version }}")
|
||||
Automated version bump to ${{ inputs.version_number }}")
|
||||
echo "pr_number=${PR_URL##*/}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Approve PR
|
||||
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }}
|
||||
run: gh pr review $PR_NUMBER --approve
|
||||
|
||||
- name: Merge PR
|
||||
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
|
||||
PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }}
|
||||
@@ -259,8 +183,8 @@ jobs:
|
||||
|
||||
cut_rc:
|
||||
name: Cut RC branch
|
||||
if: ${{ inputs.cut_rc_branch == true }}
|
||||
needs: bump_version
|
||||
if: ${{ inputs.cut_rc_branch == true }}
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout Branch
|
||||
@@ -268,28 +192,20 @@ jobs:
|
||||
with:
|
||||
ref: main
|
||||
|
||||
- name: Install xmllint
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libxml2-utils
|
||||
|
||||
- name: Verify version has been updated
|
||||
env:
|
||||
NEW_VERSION: ${{ needs.bump_version.outputs.version }}
|
||||
NEW_VERSION: ${{ inputs.version_number }}
|
||||
run: |
|
||||
# Wait for version to change.
|
||||
while : ; do
|
||||
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"])
|
||||
' src/App/Platforms/Android/AndroidManifest.xml)
|
||||
|
||||
# If the versions don't match we continue the loop, otherwise we break out of the loop.
|
||||
[[ "$NEW_VERSION" != "$CURRENT_VERSION" ]] || break
|
||||
sleep 10
|
||||
done
|
||||
done while [[ "$NEW_VERSION" != "$CURRENT_VERSION" ]]
|
||||
|
||||
- name: Cut RC branch
|
||||
run: |
|
||||
|
||||
11
.github/workflows/workflow-linter.yml
vendored
Normal file
11
.github/workflows/workflow-linter.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
name: Workflow Linter
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/**
|
||||
|
||||
jobs:
|
||||
call-workflow:
|
||||
uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@main
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<MauiVersion>8.0.7</MauiVersion>
|
||||
<MauiVersion>8.0.4-nightly.*</MauiVersion>
|
||||
<ReleaseCodesignProvision>Automatic:AppStore</ReleaseCodesignProvision>
|
||||
<ReleaseCodesignKey>iPhone Distribution</ReleaseCodesignKey>
|
||||
<IncludeBitwardeniOSExtensions>True</IncludeBitwardeniOSExtensions>
|
||||
@@ -9,8 +9,5 @@
|
||||
|
||||
<!-- Uncomment this when Unit Testing-->
|
||||
<!-- <CustomConstants>UT</CustomConstants> -->
|
||||
|
||||
<!-- Uncomment this when building FDROID-->
|
||||
<!-- <CustomConstants>FDROID</CustomConstants> -->
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -12,7 +12,7 @@ The Bitwarden mobile application is written in C# using .NET MAUI.
|
||||
|
||||
# Build/Run
|
||||
|
||||
Please refer to the [Mobile section](https://contributing.bitwarden.com/getting-started/mobile/) of the [Contributing Documentation](https://contributing.bitwarden.com/) for build instructions, recommended tooling, code style tips, and lots of other great information to get you started.
|
||||
Please refer to the [Mobile section](https://contributing.bitwarden.com/getting-started/clients/mobile/) of the [Contributing Documentation](https://contributing.bitwarden.com/) for build instructions, recommended tooling, code style tips, and lots of other great information to get you started.
|
||||
|
||||
# We're Hiring!
|
||||
|
||||
|
||||
59
build.cake
59
build.cake
@@ -15,18 +15,16 @@ abstract record VariantConfig(
|
||||
string AppName,
|
||||
string AndroidPackageName,
|
||||
string iOSBundleId,
|
||||
string ApsEnvironment,
|
||||
string DistProvisioningProfilePrefix
|
||||
string ApsEnvironment
|
||||
);
|
||||
|
||||
const string BASE_BUNDLE_ID_DROID = "com.x8bit.bitwarden";
|
||||
const string BASE_BUNDLE_ID_IOS = "com.8bit.bitwarden";
|
||||
|
||||
//NOTE: Beta iOS variants have a different ITSEncryptionExportComplianceCode
|
||||
record Dev(): VariantConfig("Bitwarden Dev", $"{BASE_BUNDLE_ID_DROID}.dev", $"{BASE_BUNDLE_ID_IOS}.dev", "development", "Dist:");
|
||||
record QA(): VariantConfig("Bitwarden QA", $"{BASE_BUNDLE_ID_DROID}.qa", $"{BASE_BUNDLE_ID_IOS}.qa", "development", "Dist:");
|
||||
record Beta(): VariantConfig("Bitwarden Beta", $"{BASE_BUNDLE_ID_DROID}.beta", $"{BASE_BUNDLE_ID_IOS}.beta", "production", "Dist: Beta");
|
||||
record Prod(): VariantConfig("Bitwarden", $"{BASE_BUNDLE_ID_DROID}", $"{BASE_BUNDLE_ID_IOS}", "production", "Dist:");
|
||||
record Dev(): VariantConfig("Bitwarden Dev", $"{BASE_BUNDLE_ID_DROID}.dev", $"{BASE_BUNDLE_ID_IOS}.dev", "development");
|
||||
record QA(): VariantConfig("Bitwarden QA", $"{BASE_BUNDLE_ID_DROID}.qa", $"{BASE_BUNDLE_ID_IOS}.qa", "development");
|
||||
record Beta(): VariantConfig("Bitwarden Beta", $"{BASE_BUNDLE_ID_DROID}.beta", $"{BASE_BUNDLE_ID_IOS}.beta", "production");
|
||||
record Prod(): VariantConfig("Bitwarden", $"{BASE_BUNDLE_ID_DROID}", $"{BASE_BUNDLE_ID_IOS}", "production");
|
||||
|
||||
VariantConfig GetVariant() => variant.ToLower() switch{
|
||||
"qa" => new QA(),
|
||||
@@ -199,8 +197,7 @@ private void UpdateiOSInfoPlist(string plistPath, VariantConfig buildVariant, Gi
|
||||
var prevBundleId = plist["CFBundleIdentifier"];
|
||||
var prevBundleName = plist["CFBundleName"];
|
||||
//var newVersion = CreateBuildNumber(prevVersion).ToString();
|
||||
// we need to maintain version formatting here composed of one to three period-separated integers, so we cannot use the GetVersionName method as in Android for non-Prod.
|
||||
var newVersionName = prevVersionName;
|
||||
var newVersionName = GetVersionName(prevVersionName, buildVariant, git);
|
||||
var newBundleId = GetiOSBundleId(buildVariant, projectType);
|
||||
var newBundleName = GetiOSBundleName(buildVariant, projectType);
|
||||
|
||||
@@ -222,11 +219,6 @@ private void UpdateiOSInfoPlist(string plistPath, VariantConfig buildVariant, Gi
|
||||
plist["NSExtension"]["NSExtensionAttributes"]["NSExtensionActivationRule"] = keyText.Replace("com.8bit.bitwarden", buildVariant.iOSBundleId);
|
||||
}
|
||||
|
||||
if(buildVariant is Beta)
|
||||
{
|
||||
plist["ITSEncryptionExportComplianceCode"] = "3dd3e32f-efa6-4d99-b410-28aa28b1cb77";
|
||||
}
|
||||
|
||||
SerializePlist(plistFile, plist);
|
||||
|
||||
Information($"Changed app name from {prevBundleName} to {newBundleName}");
|
||||
@@ -236,15 +228,12 @@ private void UpdateiOSInfoPlist(string plistPath, VariantConfig buildVariant, Gi
|
||||
Information($"{plistPath} updated with success!");
|
||||
}
|
||||
|
||||
private void UpdateiOSEntitlementsPlist(string entitlementsPath, VariantConfig buildVariant, bool updateApsEnv)
|
||||
private void UpdateiOSEntitlementsPlist(string entitlementsPath, VariantConfig buildVariant)
|
||||
{
|
||||
var EntitlementlistFile = File(entitlementsPath);
|
||||
dynamic Entitlements = DeserializePlist(EntitlementlistFile);
|
||||
|
||||
if (updateApsEnv)
|
||||
{
|
||||
Entitlements["aps-environment"] = buildVariant.ApsEnvironment;
|
||||
}
|
||||
Entitlements["aps-environment"] = buildVariant.ApsEnvironment;
|
||||
Entitlements["keychain-access-groups"] = new List<string>() { "$(AppIdentifierPrefix)" + buildVariant.iOSBundleId };
|
||||
Entitlements["com.apple.security.application-groups"] = new List<string>() { $"group.{buildVariant.iOSBundleId}" };;
|
||||
|
||||
@@ -283,10 +272,9 @@ private void UpdateWatchPbxproj(string pbxprojPath, string newVersion)
|
||||
const string pattern = @"MARKETING_VERSION = [^;]*;";
|
||||
|
||||
fileText = Regex.Replace(fileText, pattern, $"MARKETING_VERSION = {newVersion};");
|
||||
|
||||
FileWriteText(pbxprojPath, fileText);
|
||||
|
||||
Information($"{pbxprojPath} modified Marketing Version successfully.");
|
||||
FileWriteText(pbxprojPath, fileText);
|
||||
Information($"{pbxprojPath} modified successfully.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -339,7 +327,7 @@ Task("UpdateiOSPlist")
|
||||
var infoPath = Path.Combine(_slnPath, "src", "App", "Platforms", "iOS", "Info.plist");
|
||||
var entitlementsPath = Path.Combine(_slnPath, "src", "App", "Platforms", "iOS", "Entitlements.plist");
|
||||
UpdateiOSInfoPlist(infoPath, buildVariant, _gitVersion, iOSProjectType.MainApp);
|
||||
UpdateiOSEntitlementsPlist(entitlementsPath, buildVariant, true);
|
||||
UpdateiOSEntitlementsPlist(entitlementsPath, buildVariant);
|
||||
});
|
||||
|
||||
Task("UpdateiOSAutofillPlist")
|
||||
@@ -350,7 +338,7 @@ Task("UpdateiOSAutofillPlist")
|
||||
var infoPath = Path.Combine(_slnPath, "src", "iOS.Autofill", "Info.plist");
|
||||
var entitlementsPath = Path.Combine(_slnPath, "src", "iOS.Autofill", "Entitlements.plist");
|
||||
UpdateiOSInfoPlist(infoPath, buildVariant, _gitVersion, iOSProjectType.Autofill);
|
||||
UpdateiOSEntitlementsPlist(entitlementsPath, buildVariant, false);
|
||||
UpdateiOSEntitlementsPlist(entitlementsPath, buildVariant);
|
||||
});
|
||||
|
||||
Task("UpdateiOSExtensionPlist")
|
||||
@@ -361,7 +349,7 @@ Task("UpdateiOSExtensionPlist")
|
||||
var infoPath = Path.Combine(_slnPath, "src", "iOS.Extension", "Info.plist");
|
||||
var entitlementsPath = Path.Combine(_slnPath, "src", "iOS.Extension", "Entitlements.plist");
|
||||
UpdateiOSInfoPlist(infoPath, buildVariant, _gitVersion, iOSProjectType.Extension);
|
||||
UpdateiOSEntitlementsPlist(entitlementsPath, buildVariant, false);
|
||||
UpdateiOSEntitlementsPlist(entitlementsPath, buildVariant);
|
||||
});
|
||||
|
||||
Task("UpdateiOSShareExtensionPlist")
|
||||
@@ -372,7 +360,7 @@ Task("UpdateiOSShareExtensionPlist")
|
||||
var infoPath = Path.Combine(_slnPath, "src", "iOS.ShareExtension", "Info.plist");
|
||||
var entitlementsPath = Path.Combine(_slnPath, "src", "iOS.ShareExtension", "Entitlements.plist");
|
||||
UpdateiOSInfoPlist(infoPath, buildVariant, _gitVersion, iOSProjectType.ShareExtension);
|
||||
UpdateiOSEntitlementsPlist(entitlementsPath, buildVariant, false);
|
||||
UpdateiOSEntitlementsPlist(entitlementsPath, buildVariant);
|
||||
});
|
||||
|
||||
Task("UpdateiOSCodeFiles")
|
||||
@@ -409,22 +397,6 @@ Task("UpdateWatchKitAppInfoPlist")
|
||||
UpdateWatchKitAppInfoPlist(infoPath, buildVariant);
|
||||
});
|
||||
|
||||
Task("UpdateDistProfiles")
|
||||
.IsDependentOn("UpdateiOSCodeFiles")
|
||||
.Does(()=> {
|
||||
var buildVariant = GetVariant();
|
||||
|
||||
var filesToReplace = new string[] {
|
||||
Path.Combine(".github", "resources", "export-options-app-store.plist"),
|
||||
Path.Combine(_slnPath, "src", "watchOS", "bitwarden", "bitwarden.xcodeproj", "project.pbxproj")
|
||||
};
|
||||
|
||||
foreach(string path in filesToReplace)
|
||||
{
|
||||
ReplaceInFile(path, "Dist:", buildVariant.DistProvisioningProfilePrefix);
|
||||
}
|
||||
});
|
||||
|
||||
#endregion iOS
|
||||
|
||||
#region Main Tasks
|
||||
@@ -446,7 +418,6 @@ Task("iOS")
|
||||
.IsDependentOn("UpdateiOSCodeFiles")
|
||||
.IsDependentOn("UpdateWatchProject")
|
||||
.IsDependentOn("UpdateWatchKitAppInfoPlist")
|
||||
.IsDependentOn("UpdateDistProfiles")
|
||||
.Does(()=>
|
||||
{
|
||||
Information("iOS app updated");
|
||||
@@ -466,4 +437,4 @@ Options:
|
||||
});
|
||||
#endregion Main Tasks
|
||||
|
||||
RunTarget(target);
|
||||
RunTarget(target);
|
||||
@@ -2,9 +2,9 @@ project_id_env: _CROWDIN_PROJECT_ID
|
||||
api_token_env: CROWDIN_API_TOKEN
|
||||
preserve_hierarchy: true
|
||||
files:
|
||||
- source: /src/Core/Resources/Localization/AppResources.resx
|
||||
dest: /src/Core/Resources/Localization/%original_file_name%
|
||||
translation: /src/Core/Resources/Localization/AppResources.%two_letters_code%.resx
|
||||
- source: /src/App/Resources/AppResources.resx
|
||||
dest: /src/App/Resources/%original_file_name%
|
||||
translation: /src/App/Resources/AppResources.%two_letters_code%.resx
|
||||
update_option: update_as_unapproved
|
||||
languages_mapping:
|
||||
two_letters_code:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?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.4.0" 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.1" android:installLocation="internalOnly" package="com.x8bit.bitwarden">
|
||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
@@ -43,9 +43,6 @@
|
||||
<!-- Support for Xamarin.Essentials.Browser.OpenAsync (for Android > 11) -->
|
||||
<!-- Related docs: https://learn.microsoft.com/en-us/xamarin/essentials/open-browser?tabs=android -->
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.support.customtabs.action.CustomTabsService" />
|
||||
</intent>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<data android:scheme="http" />
|
||||
|
||||
@@ -347,7 +347,7 @@ namespace Bit.Droid.Autofill
|
||||
// InlinePresentation requires nonNull pending intent (even though we only utilize one for the
|
||||
// "my vault" presentation) so we're including an empty one here
|
||||
pendingIntent = PendingIntent.GetService(context, 0, new Intent(),
|
||||
AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.OneShot | PendingIntentFlags.UpdateCurrent, false));
|
||||
AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.OneShot | PendingIntentFlags.UpdateCurrent, true));
|
||||
}
|
||||
var slice = CreateInlinePresentationSlice(
|
||||
inlinePresentationSpec,
|
||||
|
||||
@@ -79,29 +79,24 @@ namespace Bit.Droid.Services
|
||||
}
|
||||
|
||||
var context = Android.App.Application.Context;
|
||||
var intent = context.PackageManager?.GetLaunchIntentForPackage(context.PackageName ?? string.Empty);
|
||||
var intent = new Intent(context, typeof(MainActivity));
|
||||
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);
|
||||
if(intent != null && context.PackageManager != null && !string.IsNullOrEmpty(context.PackageName))
|
||||
{
|
||||
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));
|
||||
deleteIntent.PutExtra(Bit.Core.Constants.NotificationData, JsonConvert.SerializeObject(data));
|
||||
var deletePendingIntent = PendingIntent.GetBroadcast(context, 20220802, deleteIntent, pendingIntentFlags);
|
||||
|
||||
var deleteIntent = new Intent(context, typeof(NotificationDismissReceiver));
|
||||
deleteIntent.PutExtra(Bit.Core.Constants.NotificationData, JsonConvert.SerializeObject(data));
|
||||
var deletePendingIntent = PendingIntent.GetBroadcast(context, 20220802, deleteIntent, pendingIntentFlags);
|
||||
|
||||
builder.SetContentIntent(pendingIntent)
|
||||
.SetDeleteIntent(deletePendingIntent);
|
||||
}
|
||||
|
||||
builder.SetContentTitle(title)
|
||||
var builder = new NotificationCompat.Builder(context, Bit.Core.Constants.AndroidNotificationChannelId)
|
||||
.SetContentIntent(pendingIntent)
|
||||
.SetContentTitle(title)
|
||||
.SetContentText(message)
|
||||
.SetSmallIcon(Bit.Core.Resource.Drawable.ic_notification)
|
||||
.SetColor((int)Android.Graphics.Color.White)
|
||||
.SetDeleteIntent(deletePendingIntent)
|
||||
.SetAutoCancel(true);
|
||||
|
||||
|
||||
if (data is PasswordlessNotificationData passwordlessNotificationData && passwordlessNotificationData.TimeoutInMinutes > 0)
|
||||
{
|
||||
builder.SetTimeoutAfter(passwordlessNotificationData.TimeoutInMinutes * 60000);
|
||||
|
||||
@@ -72,28 +72,17 @@ namespace Bit.Droid.Services
|
||||
|
||||
public bool LaunchApp(string appName)
|
||||
{
|
||||
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)
|
||||
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;
|
||||
}
|
||||
|
||||
public async Task ShowLoadingAsync(string text)
|
||||
|
||||
@@ -8,7 +8,6 @@ using Bit.Core.Abstractions;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Droid.Accessibility;
|
||||
using Java.Lang;
|
||||
using Bit.App.Droid.Utilities;
|
||||
|
||||
namespace Bit.Droid.Tile
|
||||
{
|
||||
@@ -77,7 +76,7 @@ namespace Bit.Droid.Tile
|
||||
var intent = new Intent(this, typeof(AccessibilityActivity));
|
||||
intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.SingleTop | ActivityFlags.ClearTop);
|
||||
intent.PutExtra("autofillTileClicked", true);
|
||||
this.StartActivityAndCollapseWithIntent(intent, isMutable: true);
|
||||
StartActivityAndCollapse(intent);
|
||||
}
|
||||
|
||||
private void ShowConfigErrorDialog()
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
using Android.App;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Service.QuickSettings;
|
||||
using Bit.App.Droid.Utilities;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Java.Lang;
|
||||
|
||||
namespace Bit.Droid.Tile
|
||||
@@ -55,7 +62,7 @@ namespace Bit.Droid.Tile
|
||||
var intent = new Intent(this, typeof(MainActivity));
|
||||
intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.SingleTop | ActivityFlags.ClearTop);
|
||||
intent.PutExtra("generatorTile", true);
|
||||
this.StartActivityAndCollapseWithIntent(intent, isMutable: false);
|
||||
StartActivityAndCollapse(intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
using Android.App;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Service.QuickSettings;
|
||||
using Bit.App.Droid.Utilities;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Java.Lang;
|
||||
|
||||
namespace Bit.Droid.Tile
|
||||
@@ -56,7 +63,7 @@ namespace Bit.Droid.Tile
|
||||
var intent = new Intent(this, typeof(MainActivity));
|
||||
intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.SingleTop | ActivityFlags.ClearTop);
|
||||
intent.PutExtra("myVaultTile", true);
|
||||
this.StartActivityAndCollapseWithIntent(intent, isMutable: false);
|
||||
StartActivityAndCollapse(intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Provider;
|
||||
using Android.Service.QuickSettings;
|
||||
using Bit.App.Utilities;
|
||||
|
||||
namespace Bit.App.Droid.Utilities
|
||||
@@ -65,26 +64,5 @@ namespace Bit.App.Droid.Utilities
|
||||
|
||||
return pendingIntentFlags;
|
||||
}
|
||||
|
||||
public static void StartActivityAndCollapseWithIntent(this TileService service, Intent intent, bool isMutable)
|
||||
{
|
||||
//For Android 14+ We need to use PendingIntent instead of Intent directly. Older versions still need to use Intent.
|
||||
if (Build.VERSION.SdkInt < BuildVersionCodes.UpsideDownCake)
|
||||
{
|
||||
service.StartActivityAndCollapse(intent);
|
||||
return;
|
||||
}
|
||||
var pendingIntent = PendingIntent.GetActivity(
|
||||
service.ApplicationContext,
|
||||
0,
|
||||
intent,
|
||||
AddPendingIntentMutabilityFlag(PendingIntentFlags.UpdateCurrent, isMutable)
|
||||
);
|
||||
if (pendingIntent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
service.StartActivityAndCollapse(pendingIntent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.8bit.bitwarden</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2024.4.0</string>
|
||||
<string>2024.2.1</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>CFBundleIconName</key>
|
||||
|
||||
@@ -46,7 +46,6 @@ namespace Bit.Core.Abstractions
|
||||
Task<CipherResponse> PutShareCipherAsync(string id, CipherShareRequest request);
|
||||
Task PutDeleteCipherAsync(string id);
|
||||
Task<CipherResponse> PutRestoreCipherAsync(string id);
|
||||
Task<bool> HasUnassignedCiphersAsync();
|
||||
Task RefreshIdentityTokenAsync();
|
||||
Task<SsoPrevalidateResponse> PreValidateSsoAsync(string identifier);
|
||||
Task<TResponse> SendAsync<TRequest, TResponse>(HttpMethod method, string path,
|
||||
|
||||
@@ -37,6 +37,5 @@ namespace Bit.Core.Abstractions
|
||||
Task<byte[]> DownloadAndDecryptAttachmentAsync(string cipherId, AttachmentView attachment, string organizationId);
|
||||
Task SoftDeleteWithServerAsync(string id);
|
||||
Task RestoreWithServerAsync(string id);
|
||||
Task<bool> VerifyOrganizationHasUnassignedItemsAsync();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,7 @@ namespace Bit.Core.Abstractions
|
||||
{
|
||||
public enum AwaiterPrecondition
|
||||
{
|
||||
EnvironmentUrlsInited,
|
||||
AndroidWindowCreated
|
||||
EnvironmentUrlsInited
|
||||
}
|
||||
|
||||
public interface IConditionedAwaiterManager
|
||||
|
||||
@@ -186,8 +186,6 @@ namespace Bit.Core.Abstractions
|
||||
Task<BwRegion?> GetActiveUserRegionAsync();
|
||||
Task<BwRegion?> GetPreAuthRegionAsync();
|
||||
Task SetPreAuthRegionAsync(BwRegion value);
|
||||
Task<bool> GetShouldCheckOrganizationUnassignedItemsAsync(string userId = null);
|
||||
Task SetShouldCheckOrganizationUnassignedItemsAsync(bool shouldCheck, string userId = null);
|
||||
[Obsolete("Use GetPinKeyEncryptedUserKeyAsync instead, left for migration purposes")]
|
||||
Task<string> GetPinProtectedAsync(string userId = null);
|
||||
[Obsolete("Use SetPinKeyEncryptedUserKeyAsync instead, left for migration purposes")]
|
||||
|
||||
@@ -9,7 +9,6 @@ using Bit.Core;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Models.Domain;
|
||||
using Bit.Core.Models.Response;
|
||||
using Bit.Core.Pages;
|
||||
using Bit.Core.Services;
|
||||
@@ -47,6 +46,7 @@ namespace Bit.App
|
||||
// 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
|
||||
private readonly Queue<Action> _onResumeActions = new Queue<Action>();
|
||||
private bool _hasNavigatedToAutofillWindow;
|
||||
|
||||
#if ANDROID
|
||||
|
||||
@@ -120,8 +120,41 @@ namespace Bit.App
|
||||
return new Window(new NavigationPage()); //No actual page needed. Only used for auto-filling the fields directly (externally)
|
||||
}
|
||||
|
||||
_isResumed = true;
|
||||
return new ResumeWindow(new NavigationPage(new AndroidNavigationRedirectPage(Options)));
|
||||
//"Internal" Autofill and Uri/Otp/CreateSend. This is where we create the autofill specific Window
|
||||
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
|
||||
_hasNavigatedToAutofillWindow = true;
|
||||
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
|
||||
var mainAppWindow = Windows.OfType<MainAppWindow>().FirstOrDefault();
|
||||
if (mainAppWindow != null)
|
||||
{
|
||||
mainAppWindow.PendingPage = new NavigationPage(homePage);
|
||||
}
|
||||
|
||||
//Create new main window
|
||||
return new MainAppWindow(new NavigationPage(homePage));
|
||||
}
|
||||
#else
|
||||
//iOS doesn't use the CreateWindow override used in Android so we just set the Application.Current.MainPage directly
|
||||
@@ -138,7 +171,7 @@ namespace Bit.App
|
||||
Application.Current.MainPage = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public App() : this(null)
|
||||
@@ -168,153 +201,132 @@ namespace Bit.App
|
||||
|
||||
_accountsManager.Init(() => Options, this);
|
||||
|
||||
_broadcasterService.Subscribe(nameof(App), BroadcastServiceMessageCallbackAsync);
|
||||
|
||||
Bootstrap();
|
||||
}
|
||||
|
||||
private async void BroadcastServiceMessageCallbackAsync(Message message)
|
||||
{
|
||||
try
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(message);
|
||||
if (message.Command == "showDialog")
|
||||
_broadcasterService.Subscribe(nameof(App), async (message) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
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 (message.Command == "showDialog")
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(details.CancelText))
|
||||
var details = message.Data as DialogDetails;
|
||||
var confirmed = true;
|
||||
var confirmText = string.IsNullOrWhiteSpace(details.ConfirmText) ?
|
||||
AppResources.Ok : details.ConfirmText;
|
||||
await MainThread.InvokeOnMainThreadAsync(async () =>
|
||||
{
|
||||
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 (!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)
|
||||
else if (message.Command == AppHelpers.RESUMED_MESSAGE_COMMAND)
|
||||
{
|
||||
Options.OtpData = new OtpData((string)message.Data);
|
||||
ResumedAsync().FireAndForget();
|
||||
}
|
||||
|
||||
await MainThread.InvokeOnMainThreadAsync(ExecuteNavigationAction);
|
||||
async Task ExecuteNavigationAction()
|
||||
else if (message.Command == "slept")
|
||||
{
|
||||
if (MainPage is TabsPage tabsPage)
|
||||
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)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(tabsPage.Navigation);
|
||||
ArgumentNullException.ThrowIfNull(tabsPage.Navigation.ModalStack);
|
||||
while (tabsPage.Navigation.ModalStack.Count > 0)
|
||||
Options.OtpData = new OtpData((string)message.Data);
|
||||
}
|
||||
|
||||
await MainThread.InvokeOnMainThreadAsync(async () =>
|
||||
{
|
||||
if (MainPage is TabsPage tabsPage)
|
||||
{
|
||||
await tabsPage.Navigation.PopModalAsync(false);
|
||||
}
|
||||
if (message.Command == POP_ALL_AND_GO_TO_AUTOFILL_CIPHERS_MESSAGE)
|
||||
{
|
||||
MainPage = new NavigationPage(new CipherSelectionPage(Options));
|
||||
}
|
||||
else if (message.Command == POP_ALL_AND_GO_TO_TAB_MYVAULT_MESSAGE)
|
||||
{
|
||||
Options.MyVaultTile = false;
|
||||
tabsPage.ResetToVaultPage();
|
||||
}
|
||||
else if (message.Command == POP_ALL_AND_GO_TO_TAB_GENERATOR_MESSAGE)
|
||||
{
|
||||
Options.GeneratorTile = false;
|
||||
tabsPage.ResetToGeneratorPage();
|
||||
}
|
||||
else if (message.Command == POP_ALL_AND_GO_TO_TAB_SEND_MESSAGE)
|
||||
{
|
||||
tabsPage.ResetToSendPage();
|
||||
}
|
||||
else if (message.Command == DeepLinkContext.NEW_OTP_MESSAGE)
|
||||
{
|
||||
tabsPage.ResetToVaultPage();
|
||||
ArgumentNullException.ThrowIfNull(tabsPage.Navigation);
|
||||
await tabsPage.Navigation.PushModalAsync(new NavigationPage(new CipherSelectionPage(Options)));
|
||||
while (tabsPage.Navigation.ModalStack.Count > 0)
|
||||
{
|
||||
await tabsPage.Navigation.PopModalAsync(false);
|
||||
}
|
||||
if (message.Command == POP_ALL_AND_GO_TO_AUTOFILL_CIPHERS_MESSAGE)
|
||||
{
|
||||
MainPage = new NavigationPage(new CipherSelectionPage(Options));
|
||||
}
|
||||
else if (message.Command == POP_ALL_AND_GO_TO_TAB_MYVAULT_MESSAGE)
|
||||
{
|
||||
Options.MyVaultTile = false;
|
||||
tabsPage.ResetToVaultPage();
|
||||
}
|
||||
else if (message.Command == POP_ALL_AND_GO_TO_TAB_GENERATOR_MESSAGE)
|
||||
{
|
||||
Options.GeneratorTile = false;
|
||||
tabsPage.ResetToGeneratorPage();
|
||||
}
|
||||
else if (message.Command == POP_ALL_AND_GO_TO_TAB_SEND_MESSAGE)
|
||||
{
|
||||
tabsPage.ResetToSendPage();
|
||||
}
|
||||
else if (message.Command == DeepLinkContext.NEW_OTP_MESSAGE)
|
||||
{
|
||||
tabsPage.ResetToVaultPage();
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (message.Command == "convertAccountToKeyConnector")
|
||||
catch (Exception ex)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(MainPage);
|
||||
await MainThread.InvokeOnMainThreadAsync(NavigateToRemoveMasterPasswordPageAction);
|
||||
async Task NavigateToRemoveMasterPasswordPageAction()
|
||||
{
|
||||
await MainPage.Navigation.PushModalAsync(
|
||||
new NavigationPage(new RemoveMasterPasswordPage()));
|
||||
}
|
||||
LoggerHelper.LogEvenIfCantBeResolved(ex);
|
||||
}
|
||||
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()
|
||||
@@ -329,6 +341,7 @@ namespace Bit.App
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var notification = await _stateService.GetPasswordlessLoginNotificationAsync();
|
||||
if (notification == null)
|
||||
{
|
||||
|
||||
@@ -46,9 +46,7 @@ namespace Bit.Core
|
||||
public const string PreLoginEmailKey = "preLoginEmailKey";
|
||||
public const string ConfigsKey = "configsKey";
|
||||
public const string DisplayEuEnvironmentFlag = "display-eu-environment";
|
||||
public const string UnassignedItemsBannerFlag = "unassigned-items-banner";
|
||||
public const string RegionEnvironment = "regionEnvironment";
|
||||
public const string DuoCallback = "bitwarden://duo-callback";
|
||||
|
||||
/// <summary>
|
||||
/// This key is used to store the value of "ShouldConnectToWatch" of the last user that had logged in
|
||||
@@ -137,7 +135,6 @@ namespace Bit.Core
|
||||
public static string ShouldConnectToWatchKey(string userId) => $"shouldConnectToWatch_{userId}";
|
||||
public static string ScreenCaptureAllowedKey(string userId) => $"screenCaptureAllowed_{userId}";
|
||||
public static string PendingAdminAuthRequest(string userId) => $"pendingAdminAuthRequest_{userId}";
|
||||
public static string ShouldCheckOrganizationUnassignedItemsKey(string userId) => $"shouldCheckOrganizationUnassignedItems_{userId}";
|
||||
[Obsolete]
|
||||
public static string KeyKey(string userId) => $"key_{userId}";
|
||||
[Obsolete]
|
||||
|
||||
@@ -53,13 +53,12 @@ namespace Bit.App.Controls
|
||||
if (BindingContext is CipherItemViewModel cipherItemVM)
|
||||
{
|
||||
cipherItemVM.IconImageSuccesfullyLoaded = true;
|
||||
|
||||
MainThread.BeginInvokeOnMainThread(() =>
|
||||
{
|
||||
Icon.IsVisible = cipherItemVM.ShowIconImage;
|
||||
IconPlaceholder.IsVisible = !cipherItemVM.ShowIconImage;
|
||||
});
|
||||
}
|
||||
MainThread.BeginInvokeOnMainThread(() =>
|
||||
{
|
||||
Icon.IsVisible = true;
|
||||
IconPlaceholder.IsVisible = false;
|
||||
});
|
||||
}
|
||||
|
||||
public void Icon_Error(object sender, FFImageLoading.Maui.CachedImageEvents.ErrorEventArgs e)
|
||||
|
||||
@@ -77,7 +77,6 @@
|
||||
<Folder Include="Resources\Localization\" />
|
||||
<Folder Include="Controls\Picker\" />
|
||||
<Folder Include="Controls\Avatar\" />
|
||||
<Folder Include="Utilities\WebAuthenticatorMAUI\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MauiImage Include="Resources\Images\dotnet_bot.svg">
|
||||
@@ -108,6 +107,5 @@
|
||||
<ItemGroup>
|
||||
<None Remove="Controls\Picker\" />
|
||||
<None Remove="Controls\Avatar\" />
|
||||
<None Remove="Utilities\WebAuthenticatorMAUI\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -25,7 +25,6 @@ namespace Bit.App.Models
|
||||
public bool CopyInsteadOfShareAfterSaving { get; set; }
|
||||
public bool HideAccountSwitcher { get; set; }
|
||||
public OtpData? OtpData { get; set; }
|
||||
public bool HasJustLoggedInOrUnlocked { get; set; }
|
||||
|
||||
public void SetAllFrom(AppOptions o)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Resources.Localization;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.Maui.Platform;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
@@ -27,7 +26,7 @@ namespace Bit.App.Pages
|
||||
_apiEntry.ReturnCommand = new Command(() => _identityEntry.Focus());
|
||||
_identityEntry.ReturnType = ReturnType.Next;
|
||||
_identityEntry.ReturnCommand = new Command(() => _iconsEntry.Focus());
|
||||
_vm.SubmitSuccessTask = () => MainThread.InvokeOnMainThreadAsync(SubmitSuccessAsync);
|
||||
_vm.SubmitSuccessAction = () => MainThread.BeginInvokeOnMainThread(async () => await SubmitSuccessAsync());
|
||||
_vm.CloseAction = async () =>
|
||||
{
|
||||
await Navigation.PopModalAsync();
|
||||
@@ -38,12 +37,6 @@ namespace Bit.App.Pages
|
||||
{
|
||||
_platformUtilsService.ShowToast("success", null, AppResources.EnvironmentSaved);
|
||||
await Navigation.PopModalAsync();
|
||||
#if ANDROID
|
||||
if (Platform.CurrentActivity.CurrentFocus != null)
|
||||
{
|
||||
Platform.CurrentActivity.HideKeyboard(Platform.CurrentActivity.CurrentFocus);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private void Close_Clicked(object sender, EventArgs e)
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Bit.App.Pages
|
||||
public string WebVaultUrl { get; set; }
|
||||
public string IconsUrl { get; set; }
|
||||
public string NotificationsUrls { get; set; }
|
||||
public Func<Task> SubmitSuccessTask { get; set; }
|
||||
public Action SubmitSuccessAction { get; set; }
|
||||
public Action CloseAction { get; set; }
|
||||
|
||||
public async Task SubmitAsync()
|
||||
@@ -73,10 +73,7 @@ namespace Bit.App.Pages
|
||||
IconsUrl = resUrls.Icons;
|
||||
NotificationsUrls = resUrls.Notifications;
|
||||
|
||||
if (SubmitSuccessTask != null)
|
||||
{
|
||||
await SubmitSuccessTask();
|
||||
}
|
||||
SubmitSuccessAction?.Invoke();
|
||||
}
|
||||
|
||||
public bool ValidateUrls()
|
||||
|
||||
@@ -12,14 +12,12 @@ namespace Bit.App.Pages
|
||||
private readonly HomeViewModel _vm;
|
||||
private readonly AppOptions _appOptions;
|
||||
private IBroadcasterService _broadcasterService;
|
||||
private IConditionedAwaiterManager _conditionedAwaiterManager;
|
||||
|
||||
readonly LazyResolve<ILogger> _logger = new LazyResolve<ILogger>();
|
||||
|
||||
public HomePage(AppOptions appOptions = null)
|
||||
{
|
||||
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>();
|
||||
_conditionedAwaiterManager = ServiceContainer.Resolve<IConditionedAwaiterManager>();
|
||||
_appOptions = appOptions;
|
||||
InitializeComponent();
|
||||
_vm = BindingContext as HomeViewModel;
|
||||
@@ -58,8 +56,6 @@ namespace Bit.App.Pages
|
||||
PerformNavigationOnAccountChangedOnLoad = false;
|
||||
accountsManager.NavigateOnAccountChangeAsync().FireAndForget();
|
||||
}
|
||||
|
||||
_conditionedAwaiterManager.SetAsCompleted(AwaiterPrecondition.AndroidWindowCreated);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -233,7 +233,6 @@ namespace Bit.App.Pages
|
||||
}
|
||||
var previousPage = await AppHelpers.ClearPreviousPage();
|
||||
|
||||
_appOptions.HasJustLoggedInOrUnlocked = true;
|
||||
App.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,6 @@ namespace Bit.App.Pages
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_appOptions.HasJustLoggedInOrUnlocked = true;
|
||||
var previousPage = await AppHelpers.ClearPreviousPage();
|
||||
App.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
}
|
||||
|
||||
@@ -195,8 +195,6 @@ namespace Bit.App.Pages
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_appOptions.HasJustLoggedInOrUnlocked = true;
|
||||
var previousPage = await AppHelpers.ClearPreviousPage();
|
||||
App.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
FontSize="Small"
|
||||
FontAttributes="Bold"/>
|
||||
<controls:MonoLabel
|
||||
Text="{Binding LoginRequest.FingerprintPhrase}"
|
||||
FormattedText="{Binding LoginRequest.FingerprintPhrase}"
|
||||
FontSize="Medium"
|
||||
TextColor="{DynamicResource FingerprintPhrase}"
|
||||
Margin="0,0,0,27"
|
||||
@@ -85,6 +85,7 @@
|
||||
<Button
|
||||
Text="{u:I18n DenyLogIn}"
|
||||
Command="{Binding RejectRequestCommand}"
|
||||
StyleClass="btn-secundary"
|
||||
AutomationId="DenyLoginButton" />
|
||||
|
||||
</StackLayout>
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
FontSize="Small"
|
||||
FontAttributes="Bold" />
|
||||
<controls:MonoLabel
|
||||
Text="{Binding FingerprintPhrase}"
|
||||
FormattedText="{Binding FingerprintPhrase}"
|
||||
FontSize="Small"
|
||||
TextColor="{DynamicResource FingerprintPhrase}"
|
||||
AutomationId="FingerprintPhraseValue" />
|
||||
|
||||
@@ -55,8 +55,6 @@ namespace Bit.App.Pages
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_appOptions.HasJustLoggedInOrUnlocked = true;
|
||||
var previousPage = await AppHelpers.ClearPreviousPage();
|
||||
App.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ namespace Bit.App.Pages
|
||||
InitializeComponent();
|
||||
_vm = BindingContext as LoginSsoPageViewModel;
|
||||
_vm.Page = this;
|
||||
_vm.FromIosExtension = _appOptions?.IosExtension ?? false;
|
||||
_vm.StartTwoFactorAction = () => MainThread.BeginInvokeOnMainThread(async () => await StartTwoFactorAsync());
|
||||
_vm.StartSetPasswordAction = () =>
|
||||
MainThread.BeginInvokeOnMainThread(async () => await StartSetPasswordAsync());
|
||||
|
||||
@@ -15,16 +15,6 @@ using Bit.Core.Utilities;
|
||||
using Microsoft.Maui.Authentication;
|
||||
using Microsoft.Maui.Networking;
|
||||
using NetworkAccess = Microsoft.Maui.Networking.NetworkAccess;
|
||||
using Org.BouncyCastle.Asn1.Ocsp;
|
||||
|
||||
#if IOS
|
||||
using AuthenticationServices;
|
||||
using Foundation;
|
||||
using UIKit;
|
||||
using WebAuthenticator = Bit.Core.Utilities.MAUI.WebAuthenticator;
|
||||
using WebAuthenticatorResult = Bit.Core.Utilities.MAUI.WebAuthenticatorResult;
|
||||
using WebAuthenticatorOptions = Bit.Core.Utilities.MAUI.WebAuthenticatorOptions;
|
||||
#endif
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
@@ -74,8 +64,6 @@ namespace Bit.App.Pages
|
||||
set => SetProperty(ref _orgIdentifier, value);
|
||||
}
|
||||
|
||||
public bool FromIosExtension { get; set; }
|
||||
|
||||
public ICommand LogInCommand { get; }
|
||||
public Action StartTwoFactorAction { get; set; }
|
||||
public Action StartSetPasswordAction { get; set; }
|
||||
@@ -165,9 +153,6 @@ namespace Bit.App.Pages
|
||||
CallbackUrl = new Uri(REDIRECT_URI),
|
||||
Url = new Uri(url),
|
||||
PrefersEphemeralWebBrowserSession = _useEphemeralWebBrowserSession,
|
||||
#if IOS
|
||||
ShouldUseSharedApplicationKeyWindow = FromIosExtension
|
||||
#endif
|
||||
});
|
||||
|
||||
var code = GetResultCode(authResult, state);
|
||||
|
||||
@@ -71,8 +71,6 @@ namespace Bit.App.Pages
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_appOptions.HasJustLoggedInOrUnlocked = true;
|
||||
var previousPage = await AppHelpers.ClearPreviousPage();
|
||||
App.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
}
|
||||
|
||||
@@ -132,26 +132,14 @@
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
<StackLayout
|
||||
Spacing="0"
|
||||
Padding="0"
|
||||
IsVisible="{Binding DuoMethod, Mode=OneWay}"
|
||||
VerticalOptions="FillAndExpand">
|
||||
<Label
|
||||
StyleClass="box"
|
||||
Text="{Binding DuoFramelessLabel}"
|
||||
HorizontalOptions="StartAndExpand"
|
||||
Margin="10,21"
|
||||
IsVisible="{Binding IsDuoFrameless}"/>
|
||||
<StackLayout Spacing="0" Padding="0" IsVisible="{Binding DuoMethod, Mode=OneWay}"
|
||||
VerticalOptions="StartAndExpand">
|
||||
<controls:HybridWebView
|
||||
x:Name="_duoWebView"
|
||||
HorizontalOptions="FillAndExpand"
|
||||
VerticalOptions="FillAndExpand"
|
||||
HeightRequest="{Binding DuoWebViewHeight, Mode=OneWay}"
|
||||
IsVisible="{Binding IsDuoFrameless, Converter={StaticResource inverseBool}}"/>
|
||||
<StackLayout
|
||||
StyleClass="box"
|
||||
VerticalOptions="End">
|
||||
HeightRequest="{Binding DuoWebViewHeight, Mode=OneWay}" />
|
||||
<StackLayout StyleClass="box" VerticalOptions="End">
|
||||
<StackLayout StyleClass="box-row, box-row-switch">
|
||||
<Label
|
||||
Text="{u:I18n RememberMe}"
|
||||
@@ -163,12 +151,6 @@
|
||||
HorizontalOptions="End" />
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
<Button Text="{u:I18n LaunchDuo}"
|
||||
Margin="10,21"
|
||||
StyleClass="btn-primary"
|
||||
Command="{Binding AuthenticateWithDuoFramelessCommand}"
|
||||
AutomationId="DuoFramelessButton"
|
||||
IsVisible="{Binding IsDuoFrameless}"/>
|
||||
</StackLayout>
|
||||
<StackLayout
|
||||
Spacing="0"
|
||||
|
||||
@@ -206,8 +206,6 @@ namespace Bit.App.Pages
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_appOptions.HasJustLoggedInOrUnlocked = true;
|
||||
var previousPage = await AppHelpers.ClearPreviousPage();
|
||||
App.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.Windows.Input;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Utilities;
|
||||
using Bit.Core;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
@@ -35,7 +34,6 @@ namespace Bit.App.Pages
|
||||
private string _webVaultUrl = "https://vault.bitwarden.com";
|
||||
private bool _enableContinue = false;
|
||||
private bool _showContinue = true;
|
||||
private bool _isDuoFrameless = false;
|
||||
private double _duoWebViewHeight;
|
||||
|
||||
public TwoFactorPageViewModel()
|
||||
@@ -58,7 +56,6 @@ namespace Bit.App.Pages
|
||||
PageTitle = AppResources.TwoStepLogin;
|
||||
SubmitCommand = CreateDefaultAsyncRelayCommand(() => MainThread.InvokeOnMainThreadAsync(async () => await SubmitAsync()), allowsMultipleExecutions: false);
|
||||
MoreCommand = CreateDefaultAsyncRelayCommand(MoreAsync, onException: _logger.Exception, allowsMultipleExecutions: false);
|
||||
AuthenticateWithDuoFramelessCommand = CreateDefaultAsyncRelayCommand(DuoFramelessAuthenticateAsync, allowsMultipleExecutions: false);
|
||||
}
|
||||
|
||||
public string TotpInstruction
|
||||
@@ -106,16 +103,6 @@ namespace Bit.App.Pages
|
||||
set => SetProperty(ref _enableContinue, value);
|
||||
}
|
||||
|
||||
public bool IsDuoFrameless
|
||||
{
|
||||
get => _isDuoFrameless;
|
||||
set => SetProperty(ref _isDuoFrameless, value, additionalPropertyNames: new string[] { nameof(DuoFramelessLabel) });
|
||||
}
|
||||
|
||||
public string DuoFramelessLabel => SelectedProviderType == TwoFactorProviderType.OrganizationDuo ?
|
||||
$"{AppResources.DuoTwoStepLoginIsRequiredForYourAccount} {AppResources.FollowTheStepsFromDuoToFinishLoggingIn}" :
|
||||
AppResources.FollowTheStepsFromDuoToFinishLoggingIn;
|
||||
|
||||
#if IOS
|
||||
public string YubikeyInstruction => AppResources.YubiKeyInstructionIos;
|
||||
#else
|
||||
@@ -138,7 +125,6 @@ namespace Bit.App.Pages
|
||||
}
|
||||
public ICommand SubmitCommand { get; }
|
||||
public ICommand MoreCommand { get; }
|
||||
public ICommand AuthenticateWithDuoFramelessCommand { get; }
|
||||
public Action TwoFactorAuthSuccessAction { get; set; }
|
||||
public Action LockAction { get; set; }
|
||||
public Action StartDeviceApprovalOptionsAction { get; set; }
|
||||
@@ -193,29 +179,15 @@ namespace Bit.App.Pages
|
||||
break;
|
||||
case TwoFactorProviderType.Duo:
|
||||
case TwoFactorProviderType.OrganizationDuo:
|
||||
IsDuoFrameless = providerData.ContainsKey("AuthUrl");
|
||||
if (!IsDuoFrameless)
|
||||
SetDuoWebViewHeight();
|
||||
var host = WebUtility.UrlEncode(providerData["Host"] as string);
|
||||
var req = WebUtility.UrlEncode(providerData["Signature"] as string);
|
||||
page.DuoWebView.Uri = $"{_webVaultUrl}/duo-connector.html?host={host}&request={req}";
|
||||
page.DuoWebView.RegisterAction(sig =>
|
||||
{
|
||||
SetDuoWebViewHeight();
|
||||
var host = WebUtility.UrlEncode(providerData["Host"] as string);
|
||||
var req = WebUtility.UrlEncode(providerData["Signature"] as string);
|
||||
page.DuoWebView.Uri = $"{_webVaultUrl}/duo-connector.html?host={host}&request={req}";
|
||||
page.DuoWebView.RegisterAction(sig =>
|
||||
{
|
||||
Token = sig;
|
||||
MainThread.BeginInvokeOnMainThread(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await SubmitAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
HandleException(ex);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
Token = sig;
|
||||
SubmitCommand.Execute(null);
|
||||
});
|
||||
break;
|
||||
case TwoFactorProviderType.Email:
|
||||
TotpInstruction = string.Format(AppResources.EnterVerificationCodeEmail,
|
||||
@@ -239,77 +211,6 @@ namespace Bit.App.Pages
|
||||
ShowContinue = !(SelectedProviderType == null || DuoMethod || Fido2Method);
|
||||
}
|
||||
|
||||
private async Task DuoFramelessAuthenticateAsync()
|
||||
{
|
||||
await _deviceActionService.ShowLoadingAsync(AppResources.Validating);
|
||||
|
||||
if (!_authService.TwoFactorProvidersData.TryGetValue(SelectedProviderType.Value, out var providerData) ||
|
||||
!providerData.TryGetValue("AuthUrl", out var urlObject))
|
||||
{
|
||||
throw new InvalidOperationException("Duo authentication error: Could not get ProviderData or AuthUrl");
|
||||
}
|
||||
|
||||
var url = urlObject as string;
|
||||
if (string.IsNullOrWhiteSpace(url))
|
||||
{
|
||||
throw new ArgumentNullException("Duo authentication error: Could not get valid auth url");
|
||||
}
|
||||
|
||||
WebAuthenticatorResult authResult;
|
||||
try
|
||||
{
|
||||
authResult = await WebAuthenticator.AuthenticateAsync(new WebAuthenticatorOptions
|
||||
{
|
||||
Url = new Uri(url),
|
||||
CallbackUrl = new Uri(Constants.DuoCallback)
|
||||
});
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
// user canceled
|
||||
await _deviceActionService.HideLoadingAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
await _deviceActionService.HideLoadingAsync();
|
||||
if (authResult == null || authResult.Properties == null)
|
||||
{
|
||||
throw new InvalidOperationException("Duo authentication error: Could not get result from authentication");
|
||||
}
|
||||
|
||||
if (authResult.Properties.TryGetValue("error", out var resultError))
|
||||
{
|
||||
_logger.Error(resultError);
|
||||
await _platformUtilsService.ShowDialogAsync(AppResources.AnErrorHasOccurred, AppResources.Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
string code = null;
|
||||
if (authResult.Properties.TryGetValue("code", out var resultCodeData))
|
||||
{
|
||||
code = Uri.UnescapeDataString(resultCodeData);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(code))
|
||||
{
|
||||
throw new ArgumentException("Duo authentication error: response code is null or empty/whitespace");
|
||||
}
|
||||
|
||||
string state = null;
|
||||
if (authResult.Properties.TryGetValue("state", out var resultStateData))
|
||||
{
|
||||
state = Uri.UnescapeDataString(resultStateData);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(state))
|
||||
{
|
||||
throw new ArgumentException("Duo authentication error: response state is null or empty/whitespace");
|
||||
}
|
||||
|
||||
Token = $"{code}|{state}";
|
||||
await SubmitAsync(true);
|
||||
}
|
||||
|
||||
public void SetDuoWebViewHeight()
|
||||
{
|
||||
var screenHeight = DeviceDisplay.MainDisplayInfo.Height / DeviceDisplay.MainDisplayInfo.Density;
|
||||
|
||||
@@ -1,40 +1,20 @@
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Models;
|
||||
using Bit.App.Pages;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Core.Pages;
|
||||
|
||||
public partial class AndroidNavigationRedirectPage : ContentPage
|
||||
{
|
||||
private AppOptions _options;
|
||||
public AndroidNavigationRedirectPage(AppOptions options)
|
||||
{
|
||||
_options = options ?? new AppOptions();
|
||||
private readonly IAccountsManager _accountsManager;
|
||||
|
||||
public AndroidNavigationRedirectPage()
|
||||
{
|
||||
_accountsManager = ServiceContainer.Resolve<IAccountsManager>("accountsManager");
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void AndroidNavigationRedirectPage_OnLoaded(object sender, EventArgs e)
|
||||
{
|
||||
if (ServiceContainer.TryResolve<IAccountsManager>(out var accountsManager))
|
||||
{
|
||||
accountsManager.NavigateOnAccountChangeAsync().FireAndForget();
|
||||
}
|
||||
else
|
||||
{
|
||||
Bit.App.App.MainPage = new NavigationPage(new HomePage(_options)); //Fallback scenario to load HomePage just in case something goes wrong when resolving IAccountsManager
|
||||
}
|
||||
|
||||
if (ServiceContainer.TryResolve<IConditionedAwaiterManager>(out var conditionedAwaiterManager))
|
||||
{
|
||||
conditionedAwaiterManager?.SetAsCompleted(AwaiterPrecondition.AndroidWindowCreated);
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.LogEvenIfCantBeResolved(new InvalidOperationException("ConditionedAwaiterManager can't be resolved on Android Navigation redirection"));
|
||||
}
|
||||
_accountsManager.NavigateOnAccountChangeAsync().FireAndForget();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,8 +266,6 @@
|
||||
AutomationId="SendShowHideOptionsButton" />
|
||||
<controls:IconButton
|
||||
x:Name="_btnOptionsUp"
|
||||
InputTransparent="True"
|
||||
MinimumWidthRequest="25"
|
||||
Text="{Binding Source={x:Static core:BitwardenIcons.ChevronUp}}"
|
||||
StyleClass="box-row-button"
|
||||
TextColor="{DynamicResource PrimaryColor}"
|
||||
@@ -276,8 +274,6 @@
|
||||
AutomationId="SendOptionsDisplayed" />
|
||||
<controls:IconButton
|
||||
x:Name="_btnOptionsDown"
|
||||
InputTransparent="True"
|
||||
MinimumWidthRequest="25"
|
||||
Text="{Binding Source={x:Static core:BitwardenIcons.AngleDown}}"
|
||||
StyleClass="box-row-button"
|
||||
TextColor="{DynamicResource PrimaryColor}"
|
||||
|
||||
@@ -50,7 +50,6 @@
|
||||
x:DataType="pages:SendGroupingsPageListItem">
|
||||
<controls:ExtendedStackLayout Orientation="Horizontal"
|
||||
StyleClass="list-row, list-row-platform"
|
||||
Spacing="6"
|
||||
AutomationId="{Binding AutomationId}">
|
||||
<controls:IconLabel Text="{Binding Icon, Mode=OneWay}"
|
||||
HorizontalOptions="Start"
|
||||
|
||||
@@ -37,9 +37,10 @@
|
||||
<Label
|
||||
Text="{u:I18n FingerprintPhrase}"
|
||||
FontSize="Small"
|
||||
Padding="0, 10, 0 ,0"
|
||||
FontAttributes="Bold"/>
|
||||
<controls:MonoLabel
|
||||
Text="{Binding FingerprintPhrase}"
|
||||
FormattedText="{Binding FingerprintPhrase}"
|
||||
Grid.Row="1"
|
||||
Grid.ColumnSpan="2"
|
||||
FontSize="Small"
|
||||
@@ -69,70 +70,64 @@
|
||||
Grid.ColumnSpan="2"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
<StackLayout
|
||||
x:Key="mainLayout"
|
||||
x:Name="_mainLayout"
|
||||
Padding="0, 10">
|
||||
<RefreshView
|
||||
IsRefreshing="{Binding IsRefreshing}"
|
||||
Command="{Binding RefreshCommand}"
|
||||
VerticalOptions="FillAndExpand"
|
||||
BackgroundColor="{DynamicResource BackgroundColor}">
|
||||
<StackLayout>
|
||||
<Image
|
||||
x:Name="_emptyPlaceholder"
|
||||
Source="empty_login_requests"
|
||||
HorizontalOptions="Center"
|
||||
WidthRequest="160"
|
||||
HeightRequest="160"
|
||||
Margin="0,70,0,0"
|
||||
IsVisible="{Binding HasLoginRequests, Converter={StaticResource inverseBool}}"
|
||||
SemanticProperties.Description="{u:I18n NoPendingRequests}" />
|
||||
<controls:CustomLabel
|
||||
StyleClass="box-label-regular"
|
||||
Text="{u:I18n NoPendingRequests}"
|
||||
IsVisible="{Binding HasLoginRequests, Converter={StaticResource inverseBool}}"
|
||||
FontAttributes="{OnPlatform iOS=Bold}"
|
||||
FontWeight="500"
|
||||
HorizontalTextAlignment="Center"
|
||||
Margin="14,10,14,0"/>
|
||||
<controls:ExtendedCollectionView
|
||||
ItemsSource="{Binding LoginRequests}"
|
||||
ItemTemplate="{StaticResource loginRequestTemplate}"
|
||||
SelectionMode="Single"
|
||||
IsVisible="{Binding HasLoginRequests}"
|
||||
ExtraDataForLogging="Login requests page" >
|
||||
<controls:ExtendedCollectionView.Behaviors>
|
||||
<xct:EventToCommandBehavior
|
||||
EventName="SelectionChanged"
|
||||
Command="{Binding AnswerRequestCommand}"
|
||||
EventArgsConverter="{StaticResource SelectionChangedEventArgsConverter}" />
|
||||
</controls:ExtendedCollectionView.Behaviors>
|
||||
</controls:ExtendedCollectionView>
|
||||
</StackLayout>
|
||||
</RefreshView>
|
||||
<controls:IconLabelButton
|
||||
VerticalOptions="End"
|
||||
Margin="10,0"
|
||||
Icon="{Binding Source={x:Static core:BitwardenIcons.Trash}}"
|
||||
Label="{u:I18n DeclineAllRequests}"
|
||||
ButtonCommand="{Binding DeclineAllRequestsCommand}"
|
||||
IsVisible="{Binding HasLoginRequests}"
|
||||
AutomationId="DeleteAllRequestsButton" />
|
||||
</StackLayout>
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
|
||||
<Grid
|
||||
RowDefinitions="*, Auto"
|
||||
Padding="0, 10">
|
||||
<RefreshView
|
||||
Grid.Row="0"
|
||||
IsRefreshing="{Binding IsRefreshing}"
|
||||
Command="{Binding RefreshCommand}"
|
||||
VerticalOptions="Fill"
|
||||
BackgroundColor="{DynamicResource BackgroundColor}">
|
||||
<Grid RowDefinitions="Auto, *">
|
||||
<VerticalStackLayout Grid.Row="0"
|
||||
HorizontalOptions="Center">
|
||||
<Image
|
||||
x:Name="_emptyPlaceholder"
|
||||
Source="empty_login_requests"
|
||||
WidthRequest="160"
|
||||
HeightRequest="160"
|
||||
Margin="0,70,0,0"
|
||||
IsVisible="{Binding HasLoginRequests, Converter={StaticResource inverseBool}}"
|
||||
SemanticProperties.Description="{u:I18n NoPendingRequests}" />
|
||||
<controls:CustomLabel
|
||||
StyleClass="box-label-regular"
|
||||
Text="{u:I18n NoPendingRequests}"
|
||||
IsVisible="{Binding HasLoginRequests, Converter={StaticResource inverseBool}}"
|
||||
FontAttributes="{OnPlatform iOS=Bold}"
|
||||
FontWeight="500"
|
||||
Margin="14,10,14,0"/>
|
||||
</VerticalStackLayout>
|
||||
<controls:ExtendedCollectionView
|
||||
Grid.Row="1"
|
||||
ItemsSource="{Binding LoginRequests}"
|
||||
ItemTemplate="{StaticResource loginRequestTemplate}"
|
||||
SelectionMode="Single"
|
||||
IsVisible="{Binding HasLoginRequests}"
|
||||
ExtraDataForLogging="Login requests page" >
|
||||
<controls:ExtendedCollectionView.Behaviors>
|
||||
<xct:EventToCommandBehavior
|
||||
EventName="SelectionChanged"
|
||||
Command="{Binding AnswerRequestCommand}"
|
||||
EventArgsConverter="{StaticResource SelectionChangedEventArgsConverter}" />
|
||||
</controls:ExtendedCollectionView.Behaviors>
|
||||
</controls:ExtendedCollectionView>
|
||||
</Grid>
|
||||
</RefreshView>
|
||||
|
||||
<controls:IconLabelButton
|
||||
Grid.Row="1"
|
||||
VerticalOptions="End"
|
||||
Margin="10,0"
|
||||
Icon="{Binding Source={x:Static core:BitwardenIcons.Trash}}"
|
||||
Label="{u:I18n DeclineAllRequests}"
|
||||
ButtonCommand="{Binding DeclineAllRequestsCommand}"
|
||||
IsVisible="{Binding HasLoginRequests}"
|
||||
AutomationId="DeleteAllRequestsButton" />
|
||||
|
||||
<Grid x:Name="_activityIndicatorGrid" Grid.Row="0" Grid.RowSpan="2" BackgroundColor="{DynamicResource BackgroundColor}">
|
||||
<ActivityIndicator IsRunning="True"
|
||||
VerticalOptions="Center"
|
||||
HorizontalOptions="Center" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<ContentView
|
||||
x:Name="_mainContent">
|
||||
</ContentView>
|
||||
|
||||
</pages:BaseContentPage>
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ using System.Threading.Tasks;
|
||||
using Bit.App.Utilities;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Models.Response;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.Maui.ApplicationModel;
|
||||
using Microsoft.Maui.Controls;
|
||||
@@ -20,6 +19,7 @@ namespace Bit.App.Pages
|
||||
public LoginPasswordlessRequestsListPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
SetActivityIndicator(_mainContent);
|
||||
_vm = BindingContext as LoginPasswordlessRequestsListViewModel;
|
||||
_vm.Page = this;
|
||||
}
|
||||
@@ -27,21 +27,9 @@ namespace Bit.App.Pages
|
||||
protected override async void OnAppearing()
|
||||
{
|
||||
base.OnAppearing();
|
||||
try
|
||||
{
|
||||
_activityIndicatorGrid.IsVisible = true;
|
||||
await LoadOnAppearedAsync(_mainLayout, false, _vm.RefreshAsync, _mainContent);
|
||||
|
||||
await _vm.RefreshAsync();
|
||||
UpdatePlaceholder();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.LogEvenIfCantBeResolved(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_activityIndicatorGrid.IsVisible = false;
|
||||
}
|
||||
UpdatePlaceholder();
|
||||
}
|
||||
|
||||
private async void Close_Clicked(object sender, System.EventArgs e)
|
||||
|
||||
@@ -66,6 +66,7 @@ namespace Bit.App.Pages
|
||||
{
|
||||
try
|
||||
{
|
||||
IsRefreshing = true;
|
||||
LoginRequests.ReplaceRange(await _authService.GetActivePasswordlessLoginRequestsAsync());
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -107,7 +108,7 @@ namespace Bit.App.Pages
|
||||
Origin = loginRequestData.Origin
|
||||
});
|
||||
|
||||
await MainThread.InvokeOnMainThreadAsync(() => Application.Current.MainPage.Navigation.PushModalAsync(new NavigationPage(page)));
|
||||
await Device.InvokeOnMainThreadAsync(() => Application.Current.MainPage.Navigation.PushModalAsync(new NavigationPage(page)));
|
||||
}
|
||||
|
||||
private async Task DeclineAllRequestsAsync()
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Bit.App.Pages
|
||||
_keyConnectorService = ServiceContainer.Resolve<IKeyConnectorService>("keyConnectorService");
|
||||
_stateService = ServiceContainer.Resolve<IStateService>();
|
||||
|
||||
_groupingsPage = new NavigationPage(new GroupingsPage(true, previousPage: previousPage, appOptions: appOptions))
|
||||
_groupingsPage = new NavigationPage(new GroupingsPage(true, previousPage: previousPage))
|
||||
{
|
||||
Title = AppResources.MyVault,
|
||||
IconImageSource = "lock.png"
|
||||
@@ -96,14 +96,6 @@ namespace Bit.App.Pages
|
||||
if (message.Command == "syncCompleted")
|
||||
{
|
||||
MainThread.BeginInvokeOnMainThread(async () => await UpdateVaultButtonTitleAsync());
|
||||
try
|
||||
{
|
||||
await ForcePasswordResetIfNeededAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Value.Exception(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
await UpdateVaultButtonTitleAsync();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Controls;
|
||||
using Bit.App.Models;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
@@ -28,7 +27,7 @@ namespace Bit.App.Pages
|
||||
|
||||
public GroupingsPage(bool mainPage, CipherType? type = null, string folderId = null,
|
||||
string collectionId = null, string pageTitle = null, string vaultFilterSelection = null,
|
||||
PreviousPageInfo previousPage = null, bool deleted = false, bool showTotp = false, AppOptions appOptions = null)
|
||||
PreviousPageInfo previousPage = null, bool deleted = false, bool showTotp = false)
|
||||
{
|
||||
_pageName = string.Concat(nameof(GroupingsPage), "_", DateTime.UtcNow.Ticks);
|
||||
InitializeComponent();
|
||||
@@ -51,7 +50,6 @@ namespace Bit.App.Pages
|
||||
_vm.CollectionId = collectionId;
|
||||
_vm.Deleted = deleted;
|
||||
_vm.ShowTotp = showTotp;
|
||||
_vm.AppOptions = appOptions;
|
||||
_previousPage = previousPage;
|
||||
if (pageTitle != null)
|
||||
{
|
||||
@@ -162,8 +160,6 @@ namespace Bit.App.Pages
|
||||
return;
|
||||
}
|
||||
|
||||
await _vm.CheckOrganizationUnassignedItemsAsync();
|
||||
|
||||
// Push registration
|
||||
var lastPushRegistration = await _stateService.GetPushLastRegistrationDateAsync();
|
||||
lastPushRegistration = lastPushRegistration.GetValueOrDefault(DateTime.MinValue);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System.Windows.Input;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Controls;
|
||||
using Bit.App.Models;
|
||||
using Bit.App.Utilities;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Enums;
|
||||
@@ -46,8 +45,6 @@ namespace Bit.App.Pages
|
||||
private readonly IPasswordRepromptService _passwordRepromptService;
|
||||
private readonly IOrganizationService _organizationService;
|
||||
private readonly IPolicyService _policyService;
|
||||
private readonly IConfigService _configService;
|
||||
private readonly IEnvironmentService _environmentService;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public GroupingsPageViewModel()
|
||||
@@ -64,8 +61,6 @@ namespace Bit.App.Pages
|
||||
_passwordRepromptService = ServiceContainer.Resolve<IPasswordRepromptService>("passwordRepromptService");
|
||||
_organizationService = ServiceContainer.Resolve<IOrganizationService>("organizationService");
|
||||
_policyService = ServiceContainer.Resolve<IPolicyService>("policyService");
|
||||
_configService = ServiceContainer.Resolve<IConfigService>();
|
||||
_environmentService = ServiceContainer.Resolve<IEnvironmentService>();
|
||||
_logger = ServiceContainer.Resolve<ILogger>("logger");
|
||||
|
||||
Loading = true;
|
||||
@@ -109,7 +104,6 @@ namespace Bit.App.Pages
|
||||
public List<Core.Models.View.CollectionView> Collections { get; set; }
|
||||
public List<TreeNode<Core.Models.View.CollectionView>> NestedCollections { get; set; }
|
||||
|
||||
public AppOptions AppOptions { get; internal set; }
|
||||
protected override ICipherService cipherService => _cipherService;
|
||||
protected override IPolicyService policyService => _policyService;
|
||||
protected override IOrganizationService organizationService => _organizationService;
|
||||
@@ -705,59 +699,5 @@ namespace Bit.App.Pages
|
||||
var folders = decFolders.Where(f => _allCiphers.Any(c => c.FolderId == f.Id)).ToList();
|
||||
return folders.Any() ? folders : null;
|
||||
}
|
||||
|
||||
internal async Task CheckOrganizationUnassignedItemsAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (AppOptions?.HasJustLoggedInOrUnlocked != true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AppOptions.HasJustLoggedInOrUnlocked = false;
|
||||
|
||||
if (!await _configService.GetFeatureFlagBoolAsync(Core.Constants.UnassignedItemsBannerFlag)
|
||||
||
|
||||
!await _stateService.GetShouldCheckOrganizationUnassignedItemsAsync())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var waitSyncTask = Task.Run(async () =>
|
||||
{
|
||||
while (_syncService.SyncInProgress)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
}
|
||||
});
|
||||
await waitSyncTask.WaitAsync(TimeSpan.FromMinutes(5));
|
||||
|
||||
if (!await _cipherService.VerifyOrganizationHasUnassignedItemsAsync())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var message = _environmentService.SelectedRegion == Core.Enums.Region.SelfHosted
|
||||
? AppResources.OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong
|
||||
: AppResources.OrganizationUnassignedItemsMessageUSEUDescriptionLong;
|
||||
|
||||
var response = await _deviceActionService.DisplayAlertAsync(AppResources.Notice,
|
||||
message,
|
||||
null,
|
||||
AppResources.RemindMeLater,
|
||||
AppResources.Ok);
|
||||
|
||||
if (response == AppResources.Ok)
|
||||
{
|
||||
await _stateService.SetShouldCheckOrganizationUnassignedItemsAsync(false);
|
||||
}
|
||||
}
|
||||
catch (TimeoutException) { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Exception(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2335,15 +2335,6 @@ namespace Bit.Core.Resources.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Duo two-step login is required for your account. .
|
||||
/// </summary>
|
||||
public static string DuoTwoStepLoginIsRequiredForYourAccount {
|
||||
get {
|
||||
return ResourceManager.GetString("DuoTwoStepLoginIsRequiredForYourAccount", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Edit.
|
||||
/// </summary>
|
||||
@@ -3208,15 +3199,6 @@ namespace Bit.Core.Resources.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Follow the steps from Duo to finish logging in..
|
||||
/// </summary>
|
||||
public static string FollowTheStepsFromDuoToFinishLoggingIn {
|
||||
get {
|
||||
return ResourceManager.GetString("FollowTheStepsFromDuoToFinishLoggingIn", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0} is not correctly formatted..
|
||||
/// </summary>
|
||||
@@ -3811,15 +3793,6 @@ namespace Bit.Core.Resources.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Launch Duo.
|
||||
/// </summary>
|
||||
public static string LaunchDuo {
|
||||
get {
|
||||
return ResourceManager.GetString("LaunchDuo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Bitwarden allows you to share your vault items with others by using an organization. Learn more on the bitwarden.com website..
|
||||
/// </summary>
|
||||
@@ -4866,15 +4839,6 @@ namespace Bit.Core.Resources.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Notice.
|
||||
/// </summary>
|
||||
public static string Notice {
|
||||
get {
|
||||
return ResourceManager.GetString("Notice", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to This account has two-step login set up, however, none of the configured two-step providers are supported on this device. Please use a supported device and/or add additional providers that are better supported across devices (such as an authenticator app)..
|
||||
/// </summary>
|
||||
@@ -5110,24 +5074,6 @@ namespace Bit.Core.Resources.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to On May 16, 2024, unassigned organization items will no longer be visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible..
|
||||
/// </summary>
|
||||
public static string OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong {
|
||||
get {
|
||||
return ResourceManager.GetString("OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible..
|
||||
/// </summary>
|
||||
public static string OrganizationUnassignedItemsMessageUSEUDescriptionLong {
|
||||
get {
|
||||
return ResourceManager.GetString("OrganizationUnassignedItemsMessageUSEUDescriptionLong", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Organization identifier.
|
||||
/// </summary>
|
||||
@@ -5705,15 +5651,6 @@ namespace Bit.Core.Resources.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Remind me later.
|
||||
/// </summary>
|
||||
public static string RemindMeLater {
|
||||
get {
|
||||
return ResourceManager.GetString("RemindMeLater", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Remove.
|
||||
/// </summary>
|
||||
|
||||
@@ -2876,13 +2876,4 @@ Wil u na die rekening omskakel?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Duo two-step login is required for your account. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Follow the steps from Duo to finish logging in.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Launch Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -276,7 +276,7 @@
|
||||
<value>هل أنت متأكد من أنك تريد تسجيل الخروج؟</value>
|
||||
</data>
|
||||
<data name="RemoveAccount" xml:space="preserve">
|
||||
<value>أزِل الحساب</value>
|
||||
<value>إزالة الحساب</value>
|
||||
</data>
|
||||
<data name="RemoveAccountConfirmation" xml:space="preserve">
|
||||
<value>هل أنت متأكد من أنك تريد إزالة هذا الحساب؟</value>
|
||||
@@ -2822,7 +2822,7 @@
|
||||
<value>مواصلة الاتصال بالدعم؟</value>
|
||||
</data>
|
||||
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
|
||||
<value>هل تريد المتابعة إلى سياسة الخصوصية؟</value>
|
||||
<value>Continue to privacy policy?</value>
|
||||
</data>
|
||||
<data name="ContinueToAppStore" xml:space="preserve">
|
||||
<value>هل تريد المتابعة إلى متجر التطبيقات؟</value>
|
||||
@@ -2844,7 +2844,7 @@
|
||||
<value>لا يمكن العثور على ما تبحث عنه؟ قم بالتواصل مع دعم Bitwarden على bitwarden.com.</value>
|
||||
</data>
|
||||
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
|
||||
<value>اطلع على سياستنا للخصوصية على bitwarden.com.</value>
|
||||
<value>Check out our privacy policy on bitwarden.com.</value>
|
||||
</data>
|
||||
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
|
||||
<value>استكشف المزيد من الميزات لحساب Bitwarden الخاص بك على تطبيق الويب.</value>
|
||||
@@ -2877,13 +2877,4 @@
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>أعدنّ ميزة إلغاء القُفْل لتغيير إجراء مهلة المخزن الخاص بك.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>تسجيل الدخول لـ Duo من خطوتين مطلوب لحسابك. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>اتبع الخطوات من Duo لإنهاء تسجيل الدخول.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>تشغيل Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2875,13 +2875,4 @@ Bu hesaba keçmək istəyirsiniz?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Anbar vaxt bitməsi əməliyyatınızı dəyişdirmək üçün bir kilid açma seçimi qurun.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Hesabınız üçün Duo iki addımlı giriş tələb olunur. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Giriş etməni tamamlamaq üçün Duo-dakı addımları izləyin.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Duo-nu başlat</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2623,22 +2623,22 @@
|
||||
<value>Бягучы асноўны пароль</value>
|
||||
</data>
|
||||
<data name="LoggedIn" xml:space="preserve">
|
||||
<value>Вы ўвайшлі!</value>
|
||||
<value>Logged in!</value>
|
||||
</data>
|
||||
<data name="ApproveWithMyOtherDevice" xml:space="preserve">
|
||||
<value>Approve with my other device</value>
|
||||
</data>
|
||||
<data name="RequestAdminApproval" xml:space="preserve">
|
||||
<value>Запытаць ухваленне адміністратара</value>
|
||||
<value>Request admin approval</value>
|
||||
</data>
|
||||
<data name="ApproveWithMasterPassword" xml:space="preserve">
|
||||
<value>Ухваліць з дапамогай асноўнага пароля</value>
|
||||
<value>Approve with master password</value>
|
||||
</data>
|
||||
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
|
||||
<value>Turn off using a public device</value>
|
||||
</data>
|
||||
<data name="RememberThisDevice" xml:space="preserve">
|
||||
<value>Запомніць гэту прыладу</value>
|
||||
<value>Remember this device</value>
|
||||
</data>
|
||||
<data name="Passkey" xml:space="preserve">
|
||||
<value>Passkey</value>
|
||||
@@ -2677,19 +2677,19 @@
|
||||
<value>Памылковы токен API</value>
|
||||
</data>
|
||||
<data name="AdminApprovalRequested" xml:space="preserve">
|
||||
<value>Патрабуецца ўхваленне адміністратара</value>
|
||||
<value>Admin approval requested</value>
|
||||
</data>
|
||||
<data name="YourRequestHasBeenSentToYourAdmin" xml:space="preserve">
|
||||
<value>Ваш запыт адпраўлены адміністратару.</value>
|
||||
<value>Your request has been sent to your admin.</value>
|
||||
</data>
|
||||
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
|
||||
<value>Вы атрымаеце апавяшчэння пасля яго ўхвалення. </value>
|
||||
<value>You will be notified once approved. </value>
|
||||
</data>
|
||||
<data name="TroubleLoggingIn" xml:space="preserve">
|
||||
<value>Праблемы з уваходам?</value>
|
||||
<value>Trouble logging in?</value>
|
||||
</data>
|
||||
<data name="LoggingInAsX" xml:space="preserve">
|
||||
<value>Увайсці як {0}</value>
|
||||
<value>Logging in as {0}</value>
|
||||
</data>
|
||||
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
|
||||
<value>Vault timeout action changed to log out</value>
|
||||
@@ -2738,7 +2738,7 @@
|
||||
<value>Немагчыма рэдагаваць некалькі URI адначасова</value>
|
||||
</data>
|
||||
<data name="LoginApproved" xml:space="preserve">
|
||||
<value>Уваход ухвалены</value>
|
||||
<value>Login approved</value>
|
||||
</data>
|
||||
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
|
||||
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
|
||||
@@ -2747,28 +2747,28 @@
|
||||
<value>Log in with device</value>
|
||||
</data>
|
||||
<data name="LoggingInOn" xml:space="preserve">
|
||||
<value>Увайсці на</value>
|
||||
<value>Logging in on</value>
|
||||
</data>
|
||||
<data name="Vault" xml:space="preserve">
|
||||
<value>Сховішча</value>
|
||||
<value>Vault</value>
|
||||
</data>
|
||||
<data name="Appearance" xml:space="preserve">
|
||||
<value>Знешні выгляд</value>
|
||||
<value>Appearance</value>
|
||||
</data>
|
||||
<data name="AccountSecurity" xml:space="preserve">
|
||||
<value>Бяспеке акаўнта</value>
|
||||
<value>Account security</value>
|
||||
</data>
|
||||
<data name="BitwardenHelpCenter" xml:space="preserve">
|
||||
<value>Даведачны цэнтр Bitwarden</value>
|
||||
<value>Bitwarden Help Center</value>
|
||||
</data>
|
||||
<data name="ContactBitwardenSupport" xml:space="preserve">
|
||||
<value>Звярніцеся ў службу падтрымкі Bitwarden</value>
|
||||
<value>Contact Bitwarden support</value>
|
||||
</data>
|
||||
<data name="CopyAppInformation" xml:space="preserve">
|
||||
<value>Copy app information</value>
|
||||
</data>
|
||||
<data name="SyncNow" xml:space="preserve">
|
||||
<value>Сінхранізаваць зараз</value>
|
||||
<value>Sync now</value>
|
||||
</data>
|
||||
<data name="UnlockOptions" xml:space="preserve">
|
||||
<value>Unlock options</value>
|
||||
@@ -2805,7 +2805,7 @@
|
||||
<value>Use inline autofill if your selected keyboard supports it. Otherwise, use the default overlay.</value>
|
||||
</data>
|
||||
<data name="AdditionalOptions" xml:space="preserve">
|
||||
<value>Дадатковы параметры</value>
|
||||
<value>Additional options</value>
|
||||
</data>
|
||||
<data name="ContinueToWebApp" xml:space="preserve">
|
||||
<value>Continue to web app?</value>
|
||||
@@ -2876,13 +2876,4 @@
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Duo two-step login is required for your account. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Follow the steps from Duo to finish logging in.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Launch Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2876,13 +2876,4 @@
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Задайте начин за отключване, за да може да промените действието при изтичане на времето за достъп до трезора.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Вашата регистрация изисква двустепенно удостоверяване чрез Duo. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Следвайте стъпките от Duo, за да завършите вписването.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Стартиране на Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2877,13 +2877,4 @@ Do you want to switch to this account?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Duo two-step login is required for your account. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Follow the steps from Duo to finish logging in.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Launch Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2875,13 +2875,4 @@ Skeniranje će biti izvršeno automatski.</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Duo two-step login is required for your account. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Follow the steps from Duo to finish logging in.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Launch Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2876,13 +2876,4 @@ Voleu canviar a aquest compte?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Configura una opció de desbloqueig per canviar l'acció de temps d'espera de la caixa forta.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Es requereix l'inici de sessió en dos passos de DUO al vostre compte. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Seguiu els passos de Duo per acabar d'iniciar la sessió.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Inicia DUO</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2875,13 +2875,4 @@ Chcete se přepnout na tento účet?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Nastavte volbu odemknutí, abyste změnili časový limit Vašeho trezoru.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Pro Váš účet je vyžadováno dvoufázové přihlášení DUO. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Postupujte podle kroků od DUO pro dokončení přihlášení.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Spustit DUO</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -315,7 +315,7 @@
|
||||
<comment>Label for notes.</comment>
|
||||
</data>
|
||||
<data name="Ok" xml:space="preserve">
|
||||
<value>Iawn</value>
|
||||
<value>Ok</value>
|
||||
<comment>Acknowledgement.</comment>
|
||||
</data>
|
||||
<data name="Password" xml:space="preserve">
|
||||
@@ -346,7 +346,7 @@
|
||||
<comment>Confirmation message after successfully deleting a login.</comment>
|
||||
</data>
|
||||
<data name="Submit" xml:space="preserve">
|
||||
<value>Cyflwyno</value>
|
||||
<value>Submit</value>
|
||||
</data>
|
||||
<data name="Sync" xml:space="preserve">
|
||||
<value>Cysoni</value>
|
||||
@@ -371,7 +371,7 @@
|
||||
<comment>Label for a username.</comment>
|
||||
</data>
|
||||
<data name="ValidationFieldRequired" xml:space="preserve">
|
||||
<value>Mae'r maes {0} yn ofynnol.</value>
|
||||
<value>The {0} field is required.</value>
|
||||
<comment>Validation message for when a form field is left blank and is required to be entered.</comment>
|
||||
</data>
|
||||
<data name="ValueHasBeenCopied" xml:space="preserve">
|
||||
@@ -382,7 +382,7 @@
|
||||
<value>Verify fingerprint</value>
|
||||
</data>
|
||||
<data name="VerifyMasterPassword" xml:space="preserve">
|
||||
<value>Gwirio'r prif gyfrinair</value>
|
||||
<value>Verify master password</value>
|
||||
</data>
|
||||
<data name="VerifyPIN" xml:space="preserve">
|
||||
<value>Verify PIN</value>
|
||||
@@ -407,7 +407,7 @@
|
||||
<value>Cyfrif</value>
|
||||
</data>
|
||||
<data name="AccountCreated" xml:space="preserve">
|
||||
<value>Mae eich cyfrif newydd wedi cael ei greu! Gallwch bellach fewngofnodi.</value>
|
||||
<value>Your new account has been created! You may now log in.</value>
|
||||
</data>
|
||||
<data name="AddAnItem" xml:space="preserve">
|
||||
<value>Ychwanegu eitem</value>
|
||||
@@ -784,10 +784,10 @@
|
||||
<value>Do you want to auto-fill or view this item?</value>
|
||||
</data>
|
||||
<data name="BitwardenAutofillServiceMatchConfirm" xml:space="preserve">
|
||||
<value>Ydych chi'n siŵr eich bod am lenwi'r eitem hon? Dyw hi ddim yn cyfateb yn llwyr i "{0}".</value>
|
||||
<value>Are you sure you want to auto-fill this item? It is not a complete match for "{0}".</value>
|
||||
</data>
|
||||
<data name="MatchingItems" xml:space="preserve">
|
||||
<value>Eitemau sy'n cyfateb</value>
|
||||
<value>Matching items</value>
|
||||
</data>
|
||||
<data name="PossibleMatchingItems" xml:space="preserve">
|
||||
<value>Possible matching items</value>
|
||||
@@ -799,22 +799,22 @@
|
||||
<value>You are searching for an auto-fill item for "{0}".</value>
|
||||
</data>
|
||||
<data name="LearnOrg" xml:space="preserve">
|
||||
<value>Dysgu am sefydliadau</value>
|
||||
<value>Learn about organizations</value>
|
||||
</data>
|
||||
<data name="CannotOpenApp" xml:space="preserve">
|
||||
<value>Methu agor yr ap "{0}".</value>
|
||||
<value>Cannot open the app "{0}".</value>
|
||||
<comment>Message shown when trying to launch an app that does not exist on the user's device.</comment>
|
||||
</data>
|
||||
<data name="AuthenticatorAppTitle" xml:space="preserve">
|
||||
<value>Ap dilysu</value>
|
||||
<value>Authenticator app</value>
|
||||
<comment>For 2FA</comment>
|
||||
</data>
|
||||
<data name="EnterVerificationCodeApp" xml:space="preserve">
|
||||
<value>Rhowch y cod dilysu 6 nod o'ch ap dilysu.</value>
|
||||
<value>Enter the 6 digit verification code from your authenticator app.</value>
|
||||
<comment>For 2FA</comment>
|
||||
</data>
|
||||
<data name="EnterVerificationCodeEmail" xml:space="preserve">
|
||||
<value>Rhowch y cod dilysu 6 nod anfonwyd i {0}.</value>
|
||||
<value>Enter the 6 digit verification code that was emailed to {0}.</value>
|
||||
<comment>For 2FA</comment>
|
||||
</data>
|
||||
<data name="LoginUnavailable" xml:space="preserve">
|
||||
@@ -895,7 +895,7 @@
|
||||
Scanning will happen automatically.</value>
|
||||
</data>
|
||||
<data name="ScanQrTitle" xml:space="preserve">
|
||||
<value>Sganio cod QR</value>
|
||||
<value>Scan QR Code</value>
|
||||
</data>
|
||||
<data name="Camera" xml:space="preserve">
|
||||
<value>Camera</value>
|
||||
@@ -1143,7 +1143,7 @@ Scanning will happen automatically.</value>
|
||||
<value>Icons server URL</value>
|
||||
</data>
|
||||
<data name="AutofillWithBitwarden" xml:space="preserve">
|
||||
<value>Llenwi'n awtomatig â Bitwarden</value>
|
||||
<value>Auto-fill with Bitwarden</value>
|
||||
</data>
|
||||
<data name="VaultIsLocked" xml:space="preserve">
|
||||
<value>Vault is locked</value>
|
||||
@@ -1173,7 +1173,7 @@ Scanning will happen automatically.</value>
|
||||
<value>Use the Bitwarden auto-fill service to fill login information into other apps.</value>
|
||||
</data>
|
||||
<data name="BitwardenAutofillServiceOpenAutofillSettings" xml:space="preserve">
|
||||
<value>Agor gosodiadau llenwi awtomatig</value>
|
||||
<value>Open Autofill Settings</value>
|
||||
</data>
|
||||
<data name="FaceID" xml:space="preserve">
|
||||
<value>Face ID</value>
|
||||
@@ -1256,7 +1256,7 @@ Scanning will happen automatically.</value>
|
||||
<value>Yes, and save</value>
|
||||
</data>
|
||||
<data name="AutofillAndSave" xml:space="preserve">
|
||||
<value>Llenwi'n awtomatig a chadw</value>
|
||||
<value>Auto-fill and save</value>
|
||||
</data>
|
||||
<data name="Organization" xml:space="preserve">
|
||||
<value>Sefydliad</value>
|
||||
@@ -1486,7 +1486,7 @@ Scanning will happen automatically.</value>
|
||||
<value>Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application.</value>
|
||||
</data>
|
||||
<data name="LoggedInAsOn" xml:space="preserve">
|
||||
<value>Rydych wedi mewngofnodi fel {0} ar {1}.</value>
|
||||
<value>Logged in as {0} on {1}.</value>
|
||||
<comment>ex: Logged in as user@example.com on bitwarden.com.</comment>
|
||||
</data>
|
||||
<data name="VaultLockedMasterPassword" xml:space="preserve">
|
||||
@@ -1541,7 +1541,7 @@ Scanning will happen automatically.</value>
|
||||
<comment>Color theme</comment>
|
||||
</data>
|
||||
<data name="ThemeDescription" xml:space="preserve">
|
||||
<value>Newid thema liwiau'r ap</value>
|
||||
<value>Newid thema liwiau'r ap.</value>
|
||||
</data>
|
||||
<data name="ThemeDefault" xml:space="preserve">
|
||||
<value>Rhagosodiad (system)</value>
|
||||
@@ -1577,7 +1577,7 @@ Scanning will happen automatically.</value>
|
||||
<value>Auto-fill blocked URIs</value>
|
||||
</data>
|
||||
<data name="AskToAddLogin" xml:space="preserve">
|
||||
<value>Gofyn i ychwanegu manylion mewngofnodi</value>
|
||||
<value>Ask to add login</value>
|
||||
</data>
|
||||
<data name="AskToAddLoginDescription" xml:space="preserve">
|
||||
<value>Ask to add an item if one isn't found in your vault.</value>
|
||||
@@ -1669,7 +1669,7 @@ Scanning will happen automatically.</value>
|
||||
<comment>Title for the alert to confirm vault exports.</comment>
|
||||
</data>
|
||||
<data name="Warning" xml:space="preserve">
|
||||
<value>Rhybudd</value>
|
||||
<value>Warning</value>
|
||||
</data>
|
||||
<data name="ExportVaultFailure" xml:space="preserve">
|
||||
<value>There was a problem exporting your vault. If the problem persists, you'll need to export from the web vault.</value>
|
||||
@@ -1945,7 +1945,7 @@ Scanning will happen automatically.</value>
|
||||
<value>Current access count</value>
|
||||
</data>
|
||||
<data name="NewPassword" xml:space="preserve">
|
||||
<value>Cyfrinair newydd</value>
|
||||
<value>New password</value>
|
||||
</data>
|
||||
<data name="PasswordInfo" xml:space="preserve">
|
||||
<value>Optionally require a password for users to access this Send.</value>
|
||||
@@ -2310,7 +2310,7 @@ select Add TOTP to store the key safely</value>
|
||||
<value>Caniatáu sgrinluniau</value>
|
||||
</data>
|
||||
<data name="AreYouSureYouWantToEnableScreenCapture" xml:space="preserve">
|
||||
<value>Ydych chi'n siŵr eich bod am ganiatáu sgrinluniau?</value>
|
||||
<value>Are you sure you want to turn on screen capture?</value>
|
||||
</data>
|
||||
<data name="LogInRequested" xml:space="preserve">
|
||||
<value>Login requested</value>
|
||||
@@ -2394,16 +2394,16 @@ select Add TOTP to store the key safely</value>
|
||||
<value>Gair ar hap</value>
|
||||
</data>
|
||||
<data name="EmailRequiredParenthesis" xml:space="preserve">
|
||||
<value>Ebost (gofynnol)</value>
|
||||
<value>Email (required)</value>
|
||||
</data>
|
||||
<data name="DomainNameRequiredParenthesis" xml:space="preserve">
|
||||
<value>Enw parth (gofynnol)</value>
|
||||
</data>
|
||||
<data name="APIKeyRequiredParenthesis" xml:space="preserve">
|
||||
<value>Allwedd API (gofynnol)</value>
|
||||
<value>API key (required)</value>
|
||||
</data>
|
||||
<data name="Service" xml:space="preserve">
|
||||
<value>Gwasanaeth</value>
|
||||
<value>Service</value>
|
||||
</data>
|
||||
<data name="AddyIo" xml:space="preserve">
|
||||
<value>addy.io</value>
|
||||
@@ -2549,7 +2549,7 @@ Do you want to switch to this account?</value>
|
||||
<value>Bydd angen ailgychwyn yr ap</value>
|
||||
</data>
|
||||
<data name="DefaultSystem" xml:space="preserve">
|
||||
<value>Rhagosodiad (system)</value>
|
||||
<value>Default (System)</value>
|
||||
</data>
|
||||
<data name="Important" xml:space="preserve">
|
||||
<value>Pwysig</value>
|
||||
@@ -2624,7 +2624,7 @@ Do you want to switch to this account?</value>
|
||||
<value>Prif gyfrinair presennol</value>
|
||||
</data>
|
||||
<data name="LoggedIn" xml:space="preserve">
|
||||
<value>Wedi mewngofnodi!</value>
|
||||
<value>Logged in!</value>
|
||||
</data>
|
||||
<data name="ApproveWithMyOtherDevice" xml:space="preserve">
|
||||
<value>Approve with my other device</value>
|
||||
@@ -2812,17 +2812,17 @@ Do you want to switch to this account?</value>
|
||||
<value>Parhau i'r ap gwe?</value>
|
||||
</data>
|
||||
<data name="ContinueToX" xml:space="preserve">
|
||||
<value>Parhau i {0}?</value>
|
||||
<value>Continue to {0}?</value>
|
||||
<comment>The parameter is an URL, like bitwarden.com.</comment>
|
||||
</data>
|
||||
<data name="ContinueToHelpCenter" xml:space="preserve">
|
||||
<value>Parhau i'r ganolfan gymorth?</value>
|
||||
<value>Continue to Help center?</value>
|
||||
</data>
|
||||
<data name="ContinueToContactSupport" xml:space="preserve">
|
||||
<value>Continue to contact support?</value>
|
||||
</data>
|
||||
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
|
||||
<value>Parhau i'r polisi preifatrwydd?</value>
|
||||
<value>Continue to privacy policy?</value>
|
||||
</data>
|
||||
<data name="ContinueToAppStore" xml:space="preserve">
|
||||
<value>Continue to app store?</value>
|
||||
@@ -2859,11 +2859,11 @@ Do you want to switch to this account?</value>
|
||||
<value>Choose the dark theme to use when your device’s dark mode is in use</value>
|
||||
</data>
|
||||
<data name="CreatedXY" xml:space="preserve">
|
||||
<value>Crëwyd ar {0} am {1}</value>
|
||||
<value>Created {0}, {1}</value>
|
||||
<comment>To state the date/time in which the cipher was created: Created 03/21/2023, 09:25 AM. First parameter is the date and the second parameter is the time.</comment>
|
||||
</data>
|
||||
<data name="TooManyAttempts" xml:space="preserve">
|
||||
<value>Gormod o geisiadau</value>
|
||||
<value>Too many attempts</value>
|
||||
</data>
|
||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||
<value>Account logged out.</value>
|
||||
@@ -2877,13 +2877,4 @@ Do you want to switch to this account?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Duo two-step login is required for your account. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Follow the steps from Duo to finish logging in.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Lansio Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -907,7 +907,7 @@ Skanning vil ske automatisk.</value>
|
||||
<value>Kopiér TOTP</value>
|
||||
</data>
|
||||
<data name="CopyTotpAutomaticallyDescription" xml:space="preserve">
|
||||
<value>Har et login en godkendelsesnøgle, kopiér da TOTP-bekræftelseskoden til udklipsholderen, når login autoudfyldes.</value>
|
||||
<value>Har et login en godkendelsesnøgle, så kopiér TOTP-bekræftelseskoden til udklipsholderen, når login auto-udfyldes.</value>
|
||||
</data>
|
||||
<data name="CopyTotpAutomatically" xml:space="preserve">
|
||||
<value>Kopiér TOTP automatisk</value>
|
||||
@@ -2128,7 +2128,7 @@ Skanning vil ske automatisk.</value>
|
||||
<value>Denne organisation har en virksomhedspolitik, der automatisk tilmelder dig til nulstilling af adgangskode. Tilmelding giver organisationsadministratorer mulighed for at skifte din hovedadgangskode.</value>
|
||||
</data>
|
||||
<data name="VaultTimeoutPolicyInEffect" xml:space="preserve">
|
||||
<value>Organisationspolitikkerne har sat den maksimalt tilladte bokstimeout til {0} tim(er) og {1} minut(ter).</value>
|
||||
<value>Dine organisationspolitikker påvirker din boks-timeout. Maksimum tilladte boks-timeout er {0} time(r) og {1} minut(ter)</value>
|
||||
</data>
|
||||
<data name="VaultTimeoutPolicyWithActionInEffect" xml:space="preserve">
|
||||
<value>Organisationspolitikkerne påvirker boks-timeout. Maks. tilladt boks-timeout er {0} time(r) og {1} minut(ter). Boks-timeout er pt. sat til {2}.</value>
|
||||
@@ -2354,7 +2354,7 @@ vælg Tilføj TOTP for at gemme nøglen sikkert</value>
|
||||
<value>Godkend loginanmodninger</value>
|
||||
</data>
|
||||
<data name="UseThisDeviceToApproveLoginRequestsMadeFromOtherDevices" xml:space="preserve">
|
||||
<value>Brug denne enhed til at godkende loginanmodninger fra andre enheder</value>
|
||||
<value>Brug denne enhed til at godkende loginanmodninger fra andre enheder.</value>
|
||||
</data>
|
||||
<data name="AllowNotifications" xml:space="preserve">
|
||||
<value>Tillad notifikationer</value>
|
||||
@@ -2668,7 +2668,7 @@ Vil du skifte til denne konto?</value>
|
||||
<value>Hjælp til genanmodning om hovedadgangskode</value>
|
||||
</data>
|
||||
<data name="UnlockingMayFailDueToInsufficientMemoryDecreaseYourKDFMemorySettingsToResolve" xml:space="preserve">
|
||||
<value>Oplåsning kan fejle grundet utilstrækkelig hukommelse. Reducér KDF-hukommelsesindstillinger eller opsæt biometrisk oplåsning for at afhjælpe.</value>
|
||||
<value>Unlocking may fail due to insufficient memory. Decrease your KDF memory settings or set up biometric unlock to resolve.</value>
|
||||
</data>
|
||||
<data name="InvalidAPIKey" xml:space="preserve">
|
||||
<value>Ugyldig API-nøgle</value>
|
||||
@@ -2876,13 +2876,4 @@ Vil du skifte til denne konto?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Opsæt en oplåsningsmetode for at ændre Bokstimeouthandlingen.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Duo-totrinsindlogning kræves for kontoen. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Følg trinnene fra Duo for at færdiggøre indlogningen.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Start Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2875,13 +2875,4 @@ Möchtest du zu diesem Konto wechseln?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Richte eine Entsperroption ein, um deine Aktion bei Tresor-Timeout zu ändern.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Für dein Konto ist die Duo Zwei-Faktor-Authentifizierung erforderlich. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Folge den Schritten von Duo, um die Anmeldung abzuschließen.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Duo starten</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -152,11 +152,11 @@
|
||||
<comment>Copy some value to your clipboard.</comment>
|
||||
</data>
|
||||
<data name="CopyPassword" xml:space="preserve">
|
||||
<value>Αντιγραφή κωδικού</value>
|
||||
<value>Αντιγραφή Κωδικού</value>
|
||||
<comment>The button text that allows a user to copy the login's password to their clipboard.</comment>
|
||||
</data>
|
||||
<data name="CopyUsername" xml:space="preserve">
|
||||
<value>Αντιγραφή ονόματος χρήστη</value>
|
||||
<value>Αντιγραφή Ονόματος Χρήστη</value>
|
||||
<comment>The button text that allows a user to copy the login's username to their clipboard.</comment>
|
||||
</data>
|
||||
<data name="Credits" xml:space="preserve">
|
||||
@@ -179,14 +179,14 @@
|
||||
<value>Επεξεργασία</value>
|
||||
</data>
|
||||
<data name="EditFolder" xml:space="preserve">
|
||||
<value>Επεξεργασία φακέλου</value>
|
||||
<value>Επεξεργασία Φακέλου</value>
|
||||
</data>
|
||||
<data name="Email" xml:space="preserve">
|
||||
<value>Email</value>
|
||||
<comment>Short label for an email address.</comment>
|
||||
</data>
|
||||
<data name="EmailAddress" xml:space="preserve">
|
||||
<value>Διεύθυνση email</value>
|
||||
<value>Διεύθυνση Email</value>
|
||||
<comment>Full label for a email address.</comment>
|
||||
</data>
|
||||
<data name="EmailUs" xml:space="preserve">
|
||||
@@ -203,7 +203,7 @@
|
||||
<comment>Title for your favorite items in the vault.</comment>
|
||||
</data>
|
||||
<data name="FileBugReport" xml:space="preserve">
|
||||
<value>Υποβολή αναφοράς σφάλματος</value>
|
||||
<value>Υποβολή Αναφοράς Σφάλματος</value>
|
||||
</data>
|
||||
<data name="FileBugReportDescription" xml:space="preserve">
|
||||
<value>Αναφέρετε το προβλήμα στο GitHub.</value>
|
||||
@@ -229,14 +229,14 @@
|
||||
<value>Φάκελοι</value>
|
||||
</data>
|
||||
<data name="FolderUpdated" xml:space="preserve">
|
||||
<value>Ο φάκελος ενημερώθηκε</value>
|
||||
<value>Ο φάκελος ενημερώθηκε.</value>
|
||||
</data>
|
||||
<data name="GoToWebsite" xml:space="preserve">
|
||||
<value>Μετάβαση στην ιστοσελίδα</value>
|
||||
<comment>The button text that allows user to launch the website to their web browser.</comment>
|
||||
</data>
|
||||
<data name="HelpAndFeedback" xml:space="preserve">
|
||||
<value>Βοήθεια και σχόλια</value>
|
||||
<value>Βοήθεια και Σχόλια</value>
|
||||
</data>
|
||||
<data name="Hide" xml:space="preserve">
|
||||
<value>Απόκρυψη</value>
|
||||
@@ -251,7 +251,7 @@
|
||||
<comment>Title for the alert when internet connection is required to continue.</comment>
|
||||
</data>
|
||||
<data name="InvalidMasterPassword" xml:space="preserve">
|
||||
<value>Μη έγκυρος κύριος κωδικός. Δοκιμάστε ξανά.</value>
|
||||
<value>Μη έγκυρος κύριος κωδικός, δοκιμάστε ξανά.</value>
|
||||
</data>
|
||||
<data name="InvalidPIN" xml:space="preserve">
|
||||
<value>Μη έγκυρο PIN. Προσπάθηστε ξανά.</value>
|
||||
@@ -282,7 +282,7 @@
|
||||
<value>Είστε βέβαιοι ότι θέλετε να καταργήσετε αυτόν τον λογαριασμό?</value>
|
||||
</data>
|
||||
<data name="AccountAlreadyAdded" xml:space="preserve">
|
||||
<value>Ο λογαριασμός έχει ήδη προστεθεί</value>
|
||||
<value>Ο Λογαριασμός Προστέθηκε Ήδη</value>
|
||||
</data>
|
||||
<data name="SwitchToAlreadyAddedAccountConfirmation" xml:space="preserve">
|
||||
<value>Θα θέλατε να το αλλάξετε τώρα?</value>
|
||||
@@ -296,11 +296,11 @@
|
||||
<comment>Text to define that there are more options things to see.</comment>
|
||||
</data>
|
||||
<data name="MyVault" xml:space="preserve">
|
||||
<value>Το vault μου</value>
|
||||
<value>Το Vault μου</value>
|
||||
<comment>The title for the vault page.</comment>
|
||||
</data>
|
||||
<data name="Authenticator" xml:space="preserve">
|
||||
<value>Αυθεντικοποιητής</value>
|
||||
<value>Εφαρμογή Επαλήθευσης</value>
|
||||
<comment>Authenticator TOTP feature</comment>
|
||||
</data>
|
||||
<data name="Name" xml:space="preserve">
|
||||
@@ -342,7 +342,7 @@
|
||||
<comment>Reveal a hidden value (password).</comment>
|
||||
</data>
|
||||
<data name="ItemDeleted" xml:space="preserve">
|
||||
<value>Το στοιχείο διαγράφτηκε</value>
|
||||
<value>Το στοιχείο έχει διαγραφεί.</value>
|
||||
<comment>Confirmation message after successfully deleting a login.</comment>
|
||||
</data>
|
||||
<data name="Submit" xml:space="preserve">
|
||||
@@ -375,14 +375,14 @@
|
||||
<comment>Validation message for when a form field is left blank and is required to be entered.</comment>
|
||||
</data>
|
||||
<data name="ValueHasBeenCopied" xml:space="preserve">
|
||||
<value>{0} έχει αντιγραφεί</value>
|
||||
<value>{0} έχει αντιγραφεί.</value>
|
||||
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
|
||||
</data>
|
||||
<data name="VerifyFingerprint" xml:space="preserve">
|
||||
<value>Επαλήθευση δακτυλικού αποτυπώματος</value>
|
||||
<value>Επαλήθευση Δακτυλικού Αποτυπώματος</value>
|
||||
</data>
|
||||
<data name="VerifyMasterPassword" xml:space="preserve">
|
||||
<value>Επαλήθευση κύριου κωδικού</value>
|
||||
<value>Επαλήθευση Κύριου Κωδικού</value>
|
||||
</data>
|
||||
<data name="VerifyPIN" xml:space="preserve">
|
||||
<value>Επαλήθευση PIN</value>
|
||||
@@ -413,22 +413,22 @@
|
||||
<value>Προσθήκη στοιχείου</value>
|
||||
</data>
|
||||
<data name="AppExtension" xml:space="preserve">
|
||||
<value>Επέκταση εφαρμογής</value>
|
||||
<value>Επέκταση Εφαρμογής</value>
|
||||
</data>
|
||||
<data name="AutofillAccessibilityDescription" xml:space="preserve">
|
||||
<value>Χρησιμοποιείστε την υπηρεσία προσβασιμότητας Bitwarden, για την αυτόματη συμπλήρωση συνδέσεων σε εφαρμογές και στο διαδίκτυο.</value>
|
||||
</data>
|
||||
<data name="AutofillService" xml:space="preserve">
|
||||
<value>Υπηρεσία αυτόματης συμπλήρωσης</value>
|
||||
<value>Υπηρεσία Αυτόματης Συμπλήρωσης</value>
|
||||
</data>
|
||||
<data name="AvoidAmbiguousCharacters" xml:space="preserve">
|
||||
<value>Αποφυγή αμφιλεγόμενων χαρακτήρων</value>
|
||||
<value>Αποφυγή Αμφιλεγόμενων Χαρακτήρων</value>
|
||||
</data>
|
||||
<data name="BitwardenAppExtension" xml:space="preserve">
|
||||
<value>Επέκταση εφαρμογής Bitwarden</value>
|
||||
<value>Επέκταση Εφαρμογής Bitwarden</value>
|
||||
</data>
|
||||
<data name="BitwardenAppExtensionAlert2" xml:space="preserve">
|
||||
<value>Ο ευκολότερος τρόπος για να προσθέστε νέες συνδέσεις στο vault σας, είναι μέσω της επέκτασης εφαρμογής Bitwarden. Μάθετε περισσότερα σχετικά με τη χρήση της επέκτασης εφαρμογής Bitwarden, μεταβαίνοντας στις "Ρυθμίσεις".</value>
|
||||
<value>Ο ευκολότερος τρόπος για να προσθέστε νέες συνδέσεις στο vault σας, είναι μέσω της επέκτασης εφαρμογής Bitwarden. Μάθετε περισσότερα σχετικά με τη χρήση της επέκτασης, μεταβαίνοντας στις "Ρυθμίσεις".</value>
|
||||
</data>
|
||||
<data name="BitwardenAppExtensionDescription" xml:space="preserve">
|
||||
<value>Χρήση του Bitwarden στο Safari και σε άλλες εφαρμογές για αυτόματη συμπλήρωση των συνδέσεων σας.</value>
|
||||
@@ -440,13 +440,13 @@
|
||||
<value>Χρησιμοποιείστε την υπηρεσία προσβασιμότητας Bitwarden, για την αυτόματη συμπλήρωση συνδέσεων.</value>
|
||||
</data>
|
||||
<data name="ChangeEmail" xml:space="preserve">
|
||||
<value>Αλλαγή email</value>
|
||||
<value>Αλλαγή Email</value>
|
||||
</data>
|
||||
<data name="ChangeEmailConfirmation" xml:space="preserve">
|
||||
<value>Μπορείτε να αλλάξετε τη διεύθυνση του email σας στο bitwarden.com. Θέλετε να επισκεφθείτε την ιστοσελίδα τώρα;</value>
|
||||
</data>
|
||||
<data name="ChangeMasterPassword" xml:space="preserve">
|
||||
<value>Αλλαγή κύριου κωδικού</value>
|
||||
<value>Αλλαγή Κύριου Κωδικού</value>
|
||||
</data>
|
||||
<data name="Close" xml:space="preserve">
|
||||
<value>Κλείσιμο</value>
|
||||
@@ -455,29 +455,29 @@
|
||||
<value>Συνέχεια</value>
|
||||
</data>
|
||||
<data name="CreateAccount" xml:space="preserve">
|
||||
<value>Δημιουργία λογαριασμού</value>
|
||||
<value>Δημιουργία Λογαριασμού</value>
|
||||
</data>
|
||||
<data name="CreatingAccount" xml:space="preserve">
|
||||
<value>Δημιουργία λογαριασμού...</value>
|
||||
<comment>Message shown when interacting with the server</comment>
|
||||
</data>
|
||||
<data name="EditItem" xml:space="preserve">
|
||||
<value>Επεξεργασία στοιχείου</value>
|
||||
<value>Επεξεργασία Στοιχείου</value>
|
||||
</data>
|
||||
<data name="EnableAutomaticSyncing" xml:space="preserve">
|
||||
<value>Επιτρέψτε τον αυτόματο συγχρονισμό</value>
|
||||
<value>Ενεργοποίηση Αυτόματου Συγχρονισμού</value>
|
||||
</data>
|
||||
<data name="EnterEmailForHint" xml:space="preserve">
|
||||
<value>Εισάγετε την διεύθυνση email του λογαριασμού σας, προκειμένου για να λάβετε υπόδειξη του κύριου κωδικού.</value>
|
||||
</data>
|
||||
<data name="ExntesionReenable" xml:space="preserve">
|
||||
<value>Εκ νέου ενεργοποίηση επέκτασης εφαρμογής</value>
|
||||
<value>Ενεργοποιείστε εκ νέου την Επέκτασης Εφαρμογής</value>
|
||||
</data>
|
||||
<data name="ExtensionAlmostDone" xml:space="preserve">
|
||||
<value>Σχεδόν ολοκληρώθηκε!</value>
|
||||
</data>
|
||||
<data name="ExtensionEnable" xml:space="preserve">
|
||||
<value>Ενεργοποίηση επέκτασης εφαρμογής</value>
|
||||
<value>Ενεργοποίηση Επέκτασης Εφαρμογής</value>
|
||||
</data>
|
||||
<data name="ExtensionInSafari" xml:space="preserve">
|
||||
<value>Στο Safari, βρείτε το Bitwarden χρησιμοποιώντας το εικονίδιο κοινής χρήσης (μετακινηθείτε προς τα δεξιά στην κάτω σειρά του μενού).</value>
|
||||
@@ -508,13 +508,13 @@
|
||||
<value>Δακτυλικό αποτύπωμα</value>
|
||||
</data>
|
||||
<data name="GeneratePassword" xml:space="preserve">
|
||||
<value>Παραγωγή κωδικού</value>
|
||||
<value>Δημιουργία Κωδικού</value>
|
||||
</data>
|
||||
<data name="GetPasswordHint" xml:space="preserve">
|
||||
<value>Λήψη υπόδειξης κύριου κωδικού</value>
|
||||
</data>
|
||||
<data name="ImportItems" xml:space="preserve">
|
||||
<value>Εισαγωγή στοιχείων</value>
|
||||
<value>Εισαγωγή Στοιχείων</value>
|
||||
</data>
|
||||
<data name="ImportItemsConfirmation" xml:space="preserve">
|
||||
<value>Μπορείτε να εισαγάγετε μαζικά στοιχεία διαδικτυακά στο bitwarden.com. Θέλετε να επισκεφθείτε την ιστοσελίδα τώρα;</value>
|
||||
@@ -523,7 +523,7 @@
|
||||
<value>Γρήγορη μαζική εισαγωγή των στοιχείων σας από άλλες εφαρμογές διαχείρισης κωδικών.</value>
|
||||
</data>
|
||||
<data name="LastSync" xml:space="preserve">
|
||||
<value>Τελευταίος συγχρονισμός:</value>
|
||||
<value>Τελευταίος Συγχρονισμός:</value>
|
||||
</data>
|
||||
<data name="Length" xml:space="preserve">
|
||||
<value>Μήκος</value>
|
||||
@@ -547,10 +547,10 @@
|
||||
<value>Άμεσα</value>
|
||||
</data>
|
||||
<data name="VaultTimeout" xml:space="preserve">
|
||||
<value>Χρόνος λήξης vault</value>
|
||||
<value>Χρόνος Λήξης Vault</value>
|
||||
</data>
|
||||
<data name="VaultTimeoutAction" xml:space="preserve">
|
||||
<value>Ενέργεια χρόνου λήξης vault</value>
|
||||
<value>Ενέργεια Χρόνου Λήξης Vault</value>
|
||||
</data>
|
||||
<data name="VaultTimeoutLogOutConfirmation" xml:space="preserve">
|
||||
<value>Η αποσύνδεση θα καταργήσει όλη την πρόσβαση στο vault σας και απαιτεί online έλεγχο ταυτότητας μετά το χρονικό όριο λήξης. Είστε βέβαιοι ότι θέλετε να χρησιμοποιήσετε αυτήν τη ρύθμιση;</value>
|
||||
@@ -572,7 +572,7 @@
|
||||
<value>Ο κύριος κωδικός χρησιμοποιείται για πρόσβαση στο vault σας. Είναι πολύ σημαντικό να μην τον ξεχάσετε. Δεν υπάρχει τρόπος να τον ανακτήσετε σε αυτή την περίπτωση.</value>
|
||||
</data>
|
||||
<data name="MasterPasswordHint" xml:space="preserve">
|
||||
<value>Υπόδειξη κύριου κωδικού (προαιρετικό)</value>
|
||||
<value>Υπόδειξη Κύριου Κωδικού (προαιρετικό)</value>
|
||||
</data>
|
||||
<data name="MasterPasswordHintDescription" xml:space="preserve">
|
||||
<value>Η υπόδειξη κύριου κωδικού μπορεί να σας βοηθήσει να θυμηθείτε τον κωδικό σας αν τον ξεχάσετε.</value>
|
||||
@@ -581,15 +581,15 @@
|
||||
<value>Ο κύριος κωδικός πρέπει να έχει μήκος τουλάχιστον {0} χαρακτήρες.</value>
|
||||
</data>
|
||||
<data name="MinNumbers" xml:space="preserve">
|
||||
<value>Ελάχιστα αριθμητικά ψηφία</value>
|
||||
<value>Ελάχιστα Αριθμητικά Ψηφία</value>
|
||||
<comment>Minimum numeric characters for password generator settings</comment>
|
||||
</data>
|
||||
<data name="MinSpecial" xml:space="preserve">
|
||||
<value>Ελάχιστοι ειδικοί χαρακτήρες</value>
|
||||
<value>Ελάχιστο Ειδικών Χαρακτήρων</value>
|
||||
<comment>Minimum special characters for password generator settings</comment>
|
||||
</data>
|
||||
<data name="MoreSettings" xml:space="preserve">
|
||||
<value>Περισσότερες ρυθμίσεις</value>
|
||||
<value>Περισσότερες Ρυθμίσεις</value>
|
||||
</data>
|
||||
<data name="MustLogInMainApp" xml:space="preserve">
|
||||
<value>Πρέπει να συνδεθείτε στην κύρια εφαρμογή Bitwarden για να μπορέσετε να χρησιμοποιήσετε την επέκταση.</value>
|
||||
@@ -598,7 +598,7 @@
|
||||
<value>Ποτέ</value>
|
||||
</data>
|
||||
<data name="NewItemCreated" xml:space="preserve">
|
||||
<value>Το στοιχείο προστέθηκε</value>
|
||||
<value>Δημιουργήθηκε νέο στοιχείο.</value>
|
||||
</data>
|
||||
<data name="NoFavorites" xml:space="preserve">
|
||||
<value>Δεν υπάρχουν αγαπημένα στο vault σας.</value>
|
||||
@@ -626,13 +626,13 @@
|
||||
<value>Άλλες</value>
|
||||
</data>
|
||||
<data name="PasswordGenerated" xml:space="preserve">
|
||||
<value>Ο κωδικός δημιουργήθηκε</value>
|
||||
<value>Ο κωδικός δημιουργήθηκε.</value>
|
||||
</data>
|
||||
<data name="PasswordGenerator" xml:space="preserve">
|
||||
<value>Γεννήτρια κωδικού</value>
|
||||
<value>Γεννήτρια Κωδικού</value>
|
||||
</data>
|
||||
<data name="PasswordHint" xml:space="preserve">
|
||||
<value>Υπόδειξη κωδικού</value>
|
||||
<value>Υπόδειξη Κωδικού</value>
|
||||
</data>
|
||||
<data name="PasswordHintAlert" xml:space="preserve">
|
||||
<value>Σας στείλαμε ένα email με υπόδειξη του κύριου κωδικού.</value>
|
||||
@@ -641,20 +641,20 @@
|
||||
<value>Είστε βέβαιοι ότι θέλετε να αντικαταστήσετε τον τρέχον κωδικό;</value>
|
||||
</data>
|
||||
<data name="PushNotificationAlert" xml:space="preserve">
|
||||
<value>Το Bitwarden κρατάει συγχρονισμένο το vault σας αυτόματα, με τη χρήση ειδοποιήσεων push. Για την καλύτερη δυνατή εμπειρία, επιλέξτε "Να επιτρέπεται" στην παρακάτω προτροπή όταν σας ζητηθεί να ενεργοποιήσετε τις ειδοποιήσεις push.</value>
|
||||
<value>Το Bitwarden κρατάει αυτόματα το vault σας, με τη χρήση ειδοποιήσεων push. Για την καλύτερη δυνατή εμπειρία, επιλέξτε "Να επιτρέπεται" στην παρακάτω ερώτηση, όταν σας ζητηθεί να ενεργοποιήσετε τις ειδοποιήσεις push.</value>
|
||||
<comment>Push notifications for apple products</comment>
|
||||
</data>
|
||||
<data name="RateTheApp" xml:space="preserve">
|
||||
<value>Αξιολογήστε την εφαρμογή</value>
|
||||
<value>Αξιολογήστε την Εφαρμογή</value>
|
||||
</data>
|
||||
<data name="RateTheAppDescription" xml:space="preserve">
|
||||
<value>Παρακαλούμε σκεφτείτε να μας βοηθήσετε με μια καλή κριτική!</value>
|
||||
</data>
|
||||
<data name="RegeneratePassword" xml:space="preserve">
|
||||
<value>Επαναδημιουργία κωδικού</value>
|
||||
<value>Επαναδημιουργία Κωδικού</value>
|
||||
</data>
|
||||
<data name="RetypeMasterPassword" xml:space="preserve">
|
||||
<value>Εισάγετε ξανά τον κύριο κωδικό</value>
|
||||
<value>Εισάγετε Ξανά τον Κύριο Κωδικό</value>
|
||||
</data>
|
||||
<data name="SearchVault" xml:space="preserve">
|
||||
<value>Αναζήτηση στο vault</value>
|
||||
@@ -672,10 +672,10 @@
|
||||
<value>Εισαγωγή τετραψήφιου αριθμού PIN για ξεκλείδωμα εφαρμογής.</value>
|
||||
</data>
|
||||
<data name="ItemInformation" xml:space="preserve">
|
||||
<value>Πληροφορίες στοιχείου</value>
|
||||
<value>Πληροφορίες Στοιχείου</value>
|
||||
</data>
|
||||
<data name="ItemUpdated" xml:space="preserve">
|
||||
<value>Το στοιχείο αποθηκεύτηκε</value>
|
||||
<value>Το στοιχείο ενημερώθηκε.</value>
|
||||
</data>
|
||||
<data name="Submitting" xml:space="preserve">
|
||||
<value>Υποβολή...</value>
|
||||
@@ -686,39 +686,39 @@
|
||||
<comment>Message shown when interacting with the server</comment>
|
||||
</data>
|
||||
<data name="SyncingComplete" xml:space="preserve">
|
||||
<value>Ο συγχρονισμός ολοκληρώθηκε</value>
|
||||
<value>Ο συγχρονισμός ολοκληρώθηκε.</value>
|
||||
</data>
|
||||
<data name="SyncingFailed" xml:space="preserve">
|
||||
<value>Ο συγχρονισμός απέτυχε</value>
|
||||
<value>Ο συγχρονισμός απέτυχε.</value>
|
||||
</data>
|
||||
<data name="SyncVaultNow" xml:space="preserve">
|
||||
<value>Συγχρονισμός του vault τώρα</value>
|
||||
<value>Συγχρονισμός Vault Τώρα</value>
|
||||
</data>
|
||||
<data name="TouchID" xml:space="preserve">
|
||||
<value>Touch ID</value>
|
||||
<comment>What Apple calls their fingerprint reader.</comment>
|
||||
</data>
|
||||
<data name="TwoStepLogin" xml:space="preserve">
|
||||
<value>Σύνδεση δύο βημάτων</value>
|
||||
<value>Σύνδεση σε δύο βήματα</value>
|
||||
</data>
|
||||
<data name="UnlockWith" xml:space="preserve">
|
||||
<value>Ξεκλείδωμα με {0}</value>
|
||||
</data>
|
||||
<data name="UnlockWithPIN" xml:space="preserve">
|
||||
<value>Ξεκλείδωμα με κωδικό PIN</value>
|
||||
<value>Ξεκλείδωμα με PIN</value>
|
||||
</data>
|
||||
<data name="Validating" xml:space="preserve">
|
||||
<value>Επαλήθευση</value>
|
||||
<comment>Message shown when interacting with the server</comment>
|
||||
</data>
|
||||
<data name="VerificationCode" xml:space="preserve">
|
||||
<value>Κωδικός επαλήθευσης</value>
|
||||
<value>Κωδικός Επαλήθευσης</value>
|
||||
</data>
|
||||
<data name="ViewItem" xml:space="preserve">
|
||||
<value>Προβολή στοιχείου</value>
|
||||
<value>Προβολή Στοιχείου</value>
|
||||
</data>
|
||||
<data name="WebVault" xml:space="preserve">
|
||||
<value>Διαδικτυακό vault Bitwarden</value>
|
||||
<value>Bitwarden Web Vault</value>
|
||||
</data>
|
||||
<data name="Lost2FAApp" xml:space="preserve">
|
||||
<value>Χάσατε την εφαρμογή επαλήθευσης;</value>
|
||||
@@ -728,7 +728,7 @@
|
||||
<comment>Screen title</comment>
|
||||
</data>
|
||||
<data name="ExtensionActivated" xml:space="preserve">
|
||||
<value>Η επέκταση ενεργοποιήθηκε!</value>
|
||||
<value>Η Επέκταση Ενεργοποιήθηκε!</value>
|
||||
</data>
|
||||
<data name="Icons" xml:space="preserve">
|
||||
<value>Εικονίδια</value>
|
||||
@@ -799,14 +799,14 @@
|
||||
<value>Αναζήτηση στοιχείου αυτόματης συμπλήρωσης για "{0}".</value>
|
||||
</data>
|
||||
<data name="LearnOrg" xml:space="preserve">
|
||||
<value>Μάθετε για τους οργανισμούς</value>
|
||||
<value>Μάθετε για τους Οργανισμούς</value>
|
||||
</data>
|
||||
<data name="CannotOpenApp" xml:space="preserve">
|
||||
<value>Δεν είναι δυνατή η πρόσβαση στην εφαρμογή "{0}".</value>
|
||||
<comment>Message shown when trying to launch an app that does not exist on the user's device.</comment>
|
||||
</data>
|
||||
<data name="AuthenticatorAppTitle" xml:space="preserve">
|
||||
<value>Εφαρμογή αυθεντικοποίησης</value>
|
||||
<value>Εφαρμογή Επαλήθευσης</value>
|
||||
<comment>For 2FA</comment>
|
||||
</data>
|
||||
<data name="EnterVerificationCodeApp" xml:space="preserve">
|
||||
@@ -818,14 +818,14 @@
|
||||
<comment>For 2FA</comment>
|
||||
</data>
|
||||
<data name="LoginUnavailable" xml:space="preserve">
|
||||
<value>Μη διαθέσιμη σύνδεση</value>
|
||||
<value>Μη Διαθέσιμη Σύνδεση</value>
|
||||
<comment>For 2FA whenever there are no available providers on this device.</comment>
|
||||
</data>
|
||||
<data name="NoTwoStepAvailable" xml:space="preserve">
|
||||
<value>Αυτός ο λογαριασμός έχει ενεργοποιημένη τη σύνδεση δύο βημάτων, ωστόσο, σε αυτήν τη συσκευή δεν υποστηρίζεται κανένας από τους διαμορφωμένους παρόχους δύο βημάτων. Παρακαλώ χρησιμοποιήστε μια υποστηριζόμενη συσκευή και/ή προσθέστε επιπλέον παρόχους που υποστηρίζονται καλύτερα σε όλες τις συσκευές (όπως μια εφαρμογή αυθεντικοποίησης).</value>
|
||||
<value>Αυτός ο λογαριασμός έχει ενεργοποιημένη τη σύνδεση σε δύο βήματα, ωστόσο, σε αυτήν τη συσκευή δεν υποστηρίζεται κανένας από τους διαμορφωμένους παροχείς δύο βημάτων. Χρησιμοποιήστε μια υποστηριζόμενη συσκευή και / ή προσθέστε επιπλέον παρόχους που υποστηρίζονται καλύτερα σε όλες τις συσκευές (όπως μια εφαρμογή επαλήθευσης).</value>
|
||||
</data>
|
||||
<data name="RecoveryCodeTitle" xml:space="preserve">
|
||||
<value>Κωδικός ανάκτησης</value>
|
||||
<value>Κωδικός Ανάκτησης</value>
|
||||
<comment>For 2FA</comment>
|
||||
</data>
|
||||
<data name="RememberMe" xml:space="preserve">
|
||||
@@ -837,7 +837,7 @@
|
||||
<comment>For 2FA</comment>
|
||||
</data>
|
||||
<data name="TwoStepLoginOptions" xml:space="preserve">
|
||||
<value>Επιλογές σύνδεσης δύο βημάτων</value>
|
||||
<value>Επιλογές σύνδεσης δύο παραγόντων</value>
|
||||
</data>
|
||||
<data name="UseAnotherTwoStepMethod" xml:space="preserve">
|
||||
<value>Χρήση άλλης μεθόδου δύο παραγόντων</value>
|
||||
@@ -847,18 +847,18 @@
|
||||
<comment>For 2FA</comment>
|
||||
</data>
|
||||
<data name="VerificationEmailSent" xml:space="preserve">
|
||||
<value>Το email επιβεβαίωσης στάλθηκε</value>
|
||||
<value>Το email επιβεβαίωσης στάλθηκε.</value>
|
||||
<comment>For 2FA</comment>
|
||||
</data>
|
||||
<data name="YubiKeyInstruction" xml:space="preserve">
|
||||
<value>Για να συνεχίσετε, κρατήστε το YubiKey NEO στο πίσω μέρος της συσκευής ή τοποθετήστε το YubiKey στη θύρα USB της συσκευής σας, και στη συνέχεια πατήστε το κουμπί του.</value>
|
||||
</data>
|
||||
<data name="YubiKeyTitle" xml:space="preserve">
|
||||
<value>Κλειδί ασφαλείας YubiKey</value>
|
||||
<value>Κλειδί Ασφαλείας YubiKey</value>
|
||||
<comment>"YubiKey" is the product name and should not be translated.</comment>
|
||||
</data>
|
||||
<data name="AddNewAttachment" xml:space="preserve">
|
||||
<value>Προσθήκη συνημμένου</value>
|
||||
<value>Προσθήκη Νέου Συνημμένου</value>
|
||||
</data>
|
||||
<data name="Attachments" xml:space="preserve">
|
||||
<value>Συνημμένα</value>
|
||||
@@ -878,10 +878,10 @@
|
||||
<comment>The placeholder will show the file size of the attachment. Ex "25 MB"</comment>
|
||||
</data>
|
||||
<data name="AuthenticatorKey" xml:space="preserve">
|
||||
<value>Κλειδί αυθεντικοποίησης (TOTP)</value>
|
||||
<value>Κλειδί επαλήθευσης (TOTP)</value>
|
||||
</data>
|
||||
<data name="VerificationCodeTotp" xml:space="preserve">
|
||||
<value>Κωδικός επαλήθευσης (TOTP)</value>
|
||||
<value>Κωδικός Επαλήθευσης (TOTP)</value>
|
||||
<comment>Totp code label</comment>
|
||||
</data>
|
||||
<data name="AuthenticatorKeyAdded" xml:space="preserve">
|
||||
@@ -891,8 +891,7 @@
|
||||
<value>Αδυναμία ανάγνωσης κλειδιού επαλήθευσης.</value>
|
||||
</data>
|
||||
<data name="PointYourCameraAtTheQRCode" xml:space="preserve">
|
||||
<value>Σημαδέψτε με την κάμερα σας τον κωδικό QR.
|
||||
Η σάρωση θα γίνει αυτόματα.</value>
|
||||
<value>Σημαδέψτε τον κωδικό QR με τη κάμερα. Η σάρωση θα γίνει αυτόματα.</value>
|
||||
</data>
|
||||
<data name="ScanQrTitle" xml:space="preserve">
|
||||
<value>Σάρωση κώδικα QR</value>
|
||||
@@ -907,7 +906,7 @@
|
||||
<value>Αντιγραφή TOTP</value>
|
||||
</data>
|
||||
<data name="CopyTotpAutomaticallyDescription" xml:space="preserve">
|
||||
<value>Εάν η σύνδεση έχει κάποιο κλειδί αυθεντικοποίησης, αντιγράψτε τον κωδικό επαλήθευσης TOTP στο πρόχειρο σας όταν κάνετε με αυτόματη συμπλήρωση τη συνδεση.</value>
|
||||
<value>Εάν η σύνδεση έχει κάποιο κλειδί επαλήθευσης, αντιγράψτε τον κωδικό επαλήθευσης TOTP στο πρόχειρο κάθε φορά που κάνετε αυτόματη συμπλήρωση τα στοιχεία σύνδεσης.</value>
|
||||
</data>
|
||||
<data name="CopyTotpAutomatically" xml:space="preserve">
|
||||
<value>Αυτόματη αντιγραφή TOTP</value>
|
||||
@@ -922,7 +921,7 @@
|
||||
<value>Το συνημμένο διαγράφηκε</value>
|
||||
</data>
|
||||
<data name="ChooseFile" xml:space="preserve">
|
||||
<value>Επιλογή αρχείου</value>
|
||||
<value>Επιλογή Αρχείου</value>
|
||||
</data>
|
||||
<data name="File" xml:space="preserve">
|
||||
<value>Αρχείο</value>
|
||||
@@ -946,16 +945,16 @@
|
||||
<value>Δεν μπορείτε να χρησιμοποιήσετε αυτήν τη δυνατότητα μέχρι να ενημερώσετε το κλειδί κρυπτογράφησης.</value>
|
||||
</data>
|
||||
<data name="EncryptionKeyMigrationRequiredDescriptionLong" xml:space="preserve">
|
||||
<value>Απαιτείται μεταφορά του κλειδιού κρυπτογράφησης. Παρακαλούμε συνδεθείτε μέσω του διαδικτυακού vault για να ενημερώσετε το κλειδί κρυπτογράφησης.</value>
|
||||
<value>Απαιτείται μεταφορά του κλειδιού κρυπτογράφησης. Παρακαλούμε συνδεθείτε μέσω του web vault για να ενημερώσετε το κλειδί κρυπτογράφησης.</value>
|
||||
</data>
|
||||
<data name="LearnMore" xml:space="preserve">
|
||||
<value>Μάθετε περισσότερα</value>
|
||||
<value>Μάθετε Περισσότερα</value>
|
||||
</data>
|
||||
<data name="ApiUrl" xml:space="preserve">
|
||||
<value>URL διακομιστή API</value>
|
||||
<value>URL Διακομιστή API</value>
|
||||
</data>
|
||||
<data name="CustomEnvironment" xml:space="preserve">
|
||||
<value>Προσαρμοσμένο περιβάλλον</value>
|
||||
<value>Προσαρμοσμένο Περιβάλλον</value>
|
||||
</data>
|
||||
<data name="CustomEnvironmentFooter" xml:space="preserve">
|
||||
<value>Για προχωρημένους χρήστες. Μπορείτε να ορίσετε τo URL κάθε υπηρεσίας ανεξάρτητα.</value>
|
||||
@@ -968,7 +967,7 @@
|
||||
<comment>Validation error when something is not formatted correctly, such as a URL or email address.</comment>
|
||||
</data>
|
||||
<data name="IdentityUrl" xml:space="preserve">
|
||||
<value>URL διακομιστή ταυτότητας</value>
|
||||
<value>URL Ταυτότητας Διακομιστή</value>
|
||||
<comment>"Identity" refers to an identity server. See more context here https://en.wikipedia.org/wiki/Identity_management</comment>
|
||||
</data>
|
||||
<data name="SelfHostedEnvironment" xml:space="preserve">
|
||||
@@ -981,25 +980,25 @@
|
||||
<value>URL Διακομιστή</value>
|
||||
</data>
|
||||
<data name="WebVaultUrl" xml:space="preserve">
|
||||
<value>URL διακομιστή διαδικτυακού vault</value>
|
||||
<value>URL Διακομιστή Web Vault</value>
|
||||
</data>
|
||||
<data name="BitwardenAutofillServiceNotificationContentOld" xml:space="preserve">
|
||||
<value>Πατήστε στην ειδοποίηση για να συμπληρώσετε αυτόματα ένα στοιχείο από τη λίστα σας.</value>
|
||||
</data>
|
||||
<data name="CustomFields" xml:space="preserve">
|
||||
<value>Προσαρμοσμένα πεδία</value>
|
||||
<value>Προσαρμοσμένα Πεδία</value>
|
||||
</data>
|
||||
<data name="CopyNumber" xml:space="preserve">
|
||||
<value>Αντιγραφή αριθμού</value>
|
||||
<value>Αντιγραφή Αριθμού</value>
|
||||
</data>
|
||||
<data name="CopySecurityCode" xml:space="preserve">
|
||||
<value>Αντιγραφή κωδικού ασφαλείας</value>
|
||||
<value>Αντιγραφή Κωδικού Ασφαλείας</value>
|
||||
</data>
|
||||
<data name="Number" xml:space="preserve">
|
||||
<value>Αριθμός</value>
|
||||
</data>
|
||||
<data name="SecurityCode" xml:space="preserve">
|
||||
<value>Κωδικός ασφαλείας</value>
|
||||
<value>Κωδικός Ασφαλείας</value>
|
||||
</data>
|
||||
<data name="TypeCard" xml:space="preserve">
|
||||
<value>Κάρτα</value>
|
||||
@@ -1011,7 +1010,7 @@
|
||||
<value>Σύνδεση</value>
|
||||
</data>
|
||||
<data name="TypeSecureNote" xml:space="preserve">
|
||||
<value>Ασφαλής σημείωση</value>
|
||||
<value>Ασφαλής Σημείωση</value>
|
||||
</data>
|
||||
<data name="Address1" xml:space="preserve">
|
||||
<value>Διεύθυνση 1</value>
|
||||
@@ -1050,10 +1049,10 @@
|
||||
<value>Dr</value>
|
||||
</data>
|
||||
<data name="ExpirationMonth" xml:space="preserve">
|
||||
<value>Μήνας λήξης</value>
|
||||
<value>Μήνας Λήξης</value>
|
||||
</data>
|
||||
<data name="ExpirationYear" xml:space="preserve">
|
||||
<value>Έτος λήξης</value>
|
||||
<value>Έτος Λήξης</value>
|
||||
</data>
|
||||
<data name="February" xml:space="preserve">
|
||||
<value>Φεβρουάριος</value>
|
||||
@@ -1077,7 +1076,7 @@
|
||||
<value>Ονοματεπώνυμο</value>
|
||||
</data>
|
||||
<data name="LicenseNumber" xml:space="preserve">
|
||||
<value>Αριθμός άδειας</value>
|
||||
<value>Αριθμός Άδειας</value>
|
||||
</data>
|
||||
<data name="March" xml:space="preserve">
|
||||
<value>Μάρτιος</value>
|
||||
@@ -1086,7 +1085,7 @@
|
||||
<value>Μάιος</value>
|
||||
</data>
|
||||
<data name="MiddleName" xml:space="preserve">
|
||||
<value>Μεσαίο όνομα</value>
|
||||
<value>Μεσαίο Όνομα</value>
|
||||
</data>
|
||||
<data name="Mr" xml:space="preserve">
|
||||
<value>Κος</value>
|
||||
@@ -1107,7 +1106,7 @@
|
||||
<value>Οκτώβριος</value>
|
||||
</data>
|
||||
<data name="PassportNumber" xml:space="preserve">
|
||||
<value>Αριθμός διαβατηρίου</value>
|
||||
<value>Αριθμός Διαβατηρίου</value>
|
||||
</data>
|
||||
<data name="Phone" xml:space="preserve">
|
||||
<value>Τηλέφωνο</value>
|
||||
@@ -1125,7 +1124,7 @@
|
||||
<value>Τίτλος</value>
|
||||
</data>
|
||||
<data name="ZipPostalCode" xml:space="preserve">
|
||||
<value>Ταχυδρομικός κώδικας</value>
|
||||
<value>Ταχυδρομικός Κώδικας</value>
|
||||
</data>
|
||||
<data name="Address" xml:space="preserve">
|
||||
<value>Διεύθυνση</value>
|
||||
@@ -1140,7 +1139,7 @@
|
||||
<value>Εμφάνιση μιας αναγνωρίσιμης εικόνας δίπλα σε κάθε σύνδεση.</value>
|
||||
</data>
|
||||
<data name="IconsUrl" xml:space="preserve">
|
||||
<value>URL διακομιστή εικονιδίων</value>
|
||||
<value>Εικονίδια Διακομιστή URL</value>
|
||||
</data>
|
||||
<data name="AutofillWithBitwarden" xml:space="preserve">
|
||||
<value>Αυτόματη συμπλήρωση με Bitwarden</value>
|
||||
@@ -1195,7 +1194,7 @@
|
||||
<value>Δεν ήταν δυνατό να ανοίξουμε αυτόματα το μενού ρυθμίσεων αυτόματης συμπλήρωσης Android για εσάς. Μπορείτε να πλοηγηθείτε στο μενού ρυθμίσεων αυτόματης συμπλήρωσης με μη αυτόματο τρόπο από τις Ρυθμίσεις Android > Σύστημα > Γλώσσες και εισαγωγή > Σύνθετες > Υπηρεσία αυτόματης συμπλήρωσης.</value>
|
||||
</data>
|
||||
<data name="CustomFieldName" xml:space="preserve">
|
||||
<value>Όνομα προσαρμοσμένου πεδίου</value>
|
||||
<value>Όνομα Προσαρμοσμένου Πεδίου</value>
|
||||
</data>
|
||||
<data name="FieldTypeBoolean" xml:space="preserve">
|
||||
<value>Δυαδικό</value>
|
||||
@@ -1210,7 +1209,7 @@
|
||||
<value>Κείμενο</value>
|
||||
</data>
|
||||
<data name="NewCustomField" xml:space="preserve">
|
||||
<value>Νέο προσαρμοσμένο πεδίο</value>
|
||||
<value>Νέο Προσαρμοσμένο Πεδίο</value>
|
||||
</data>
|
||||
<data name="SelectTypeField" xml:space="preserve">
|
||||
<value>Τι τύπος προσαρμοσμένου πεδίου είναι αυτό που θέλετε να προσθέσετε;</value>
|
||||
@@ -1249,11 +1248,11 @@
|
||||
<value>Εντοπισμός Αντιστοίχισης URI</value>
|
||||
</data>
|
||||
<data name="MatchDetection" xml:space="preserve">
|
||||
<value>Εντοπισμός αντιστοίχισης</value>
|
||||
<value>Εντοπισμός Αντιστοίχισης</value>
|
||||
<comment>URI match detection for auto-fill.</comment>
|
||||
</data>
|
||||
<data name="YesAndSave" xml:space="preserve">
|
||||
<value>Ναι, και αποθήκευση</value>
|
||||
<value>Αποδοχή και Αποθήκευση</value>
|
||||
</data>
|
||||
<data name="AutofillAndSave" xml:space="preserve">
|
||||
<value>Αυτόματη συμπλήρωση και αποθήκευση</value>
|
||||
@@ -1275,7 +1274,7 @@
|
||||
<value>Η υπηρεσία προσβασιμότητας μπορεί να είναι χρήσιμη όταν οι εφαρμογές δεν υποστηρίζουν την τυπική υπηρεσία αυτόματης συμπλήρωσης.</value>
|
||||
</data>
|
||||
<data name="DatePasswordUpdated" xml:space="preserve">
|
||||
<value>Ο κωδικός ενημερώθηκε</value>
|
||||
<value>Ο Κωδικός Ενημερώθηκε</value>
|
||||
<comment>ex. Date this password was updated</comment>
|
||||
</data>
|
||||
<data name="DateUpdated" xml:space="preserve">
|
||||
@@ -1298,7 +1297,7 @@
|
||||
<value>Αποκτήστε πρόσβαση στη λίστα σας απευθείας από το πληκτρολόγιό σας για γρήγορη αυτόματη συμπλήρωση κωδικών.</value>
|
||||
</data>
|
||||
<data name="AutofillTurnOn" xml:space="preserve">
|
||||
<value>Για να ενεργοποιήσετε την αυτόματη συμπλήρωση κωδικού στη συσκευή σας, ακολουθήστε αυτές τις οδηγίες:</value>
|
||||
<value>Για να ενεργοποιήσετε την αυτόματη συμπλήρωση του κωδικού στη συσκευή σας, ακολουθήστε αυτές τις οδηγίες:</value>
|
||||
</data>
|
||||
<data name="AutofillTurnOn1" xml:space="preserve">
|
||||
<value>1. Μεταβείτε στις "Ρυθμίσεις" του iOS</value>
|
||||
@@ -1316,7 +1315,7 @@
|
||||
<value>5. Επιλέξτε "Bitwarden"</value>
|
||||
</data>
|
||||
<data name="PasswordAutofill" xml:space="preserve">
|
||||
<value>Αυτόματη συμπλήρωση κωδικού</value>
|
||||
<value>Αυτόματη Συμπλήρωση Κωδικού</value>
|
||||
</data>
|
||||
<data name="BitwardenAutofillAlert2" xml:space="preserve">
|
||||
<value>Ο ευκολότερος τρόπος για να προσθέσετε νέες συνδέσεις στο vault σας, είναι με την επέκταση αυτόματης συμπλήρωσης κωδικών Bitwarden. Μάθετε περισσότερα σχετικά με τη χρήση της επέκτασης αυτής, μεταβαίνοντας στις "Ρυθμίσεις".</value>
|
||||
@@ -1334,10 +1333,10 @@
|
||||
<value>Συνδέσεις</value>
|
||||
</data>
|
||||
<data name="SecureNotes" xml:space="preserve">
|
||||
<value>Ασφαλείς σημειώσεις</value>
|
||||
<value>Ασφαλείς Σημειώσεις</value>
|
||||
</data>
|
||||
<data name="AllItems" xml:space="preserve">
|
||||
<value>Όλα τα στοιχεία</value>
|
||||
<value>Όλα τα Στοιχεία</value>
|
||||
</data>
|
||||
<data name="URIs" xml:space="preserve">
|
||||
<value>URIs</value>
|
||||
@@ -1357,13 +1356,13 @@
|
||||
<value>Ο κωδικός αυτός δεν βρέθηκε σε γνωστές διαρροές δεδομένων. Είναι ασφαλής για χρήση.</value>
|
||||
</data>
|
||||
<data name="IdentityName" xml:space="preserve">
|
||||
<value>Όνομα ταυτότητας</value>
|
||||
<value>Όνομα Ταυτότητας</value>
|
||||
</data>
|
||||
<data name="Value" xml:space="preserve">
|
||||
<value>Τιμή</value>
|
||||
</data>
|
||||
<data name="PasswordHistory" xml:space="preserve">
|
||||
<value>Ιστορικό κωδικού</value>
|
||||
<value>Ιστορικό Κωδικού</value>
|
||||
</data>
|
||||
<data name="Types" xml:space="preserve">
|
||||
<value>Τύποι</value>
|
||||
@@ -1434,13 +1433,13 @@
|
||||
<value>Επιλέξτε έναν οργανισμό στον οποίο θέλετε να μετακινήσετε αυτό το στοιχείο. Η μετακίνηση σε έναν οργανισμό μεταβιβάζει την ιδιοκτησία του στοιχείου σε αυτό τον οργανισμό. Δεν θα είστε πλέον ο άμεσος ιδιοκτήτης αυτού του στοιχείου μόλις το μετακινήσετε.</value>
|
||||
</data>
|
||||
<data name="NumberOfWords" xml:space="preserve">
|
||||
<value>Αριθμός λέξεων</value>
|
||||
<value>Αριθμός Λέξεων</value>
|
||||
</data>
|
||||
<data name="Passphrase" xml:space="preserve">
|
||||
<value>Συνθηματικό</value>
|
||||
</data>
|
||||
<data name="WordSeparator" xml:space="preserve">
|
||||
<value>Διαχωριστής λέξεων</value>
|
||||
<value>Διαχωριστής Λέξεων</value>
|
||||
</data>
|
||||
<data name="Clear" xml:space="preserve">
|
||||
<value>Εκκαθάριση</value>
|
||||
@@ -1454,7 +1453,7 @@
|
||||
<value>Δεν υπάρχουν φάκελοι προς εμφάνιση.</value>
|
||||
</data>
|
||||
<data name="FingerprintPhrase" xml:space="preserve">
|
||||
<value>Φράση δακτυλικών αποτυπωμάτων</value>
|
||||
<value>Φράση Δακτυλικών Αποτυπωμάτων</value>
|
||||
<comment>A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing.</comment>
|
||||
</data>
|
||||
<data name="YourAccountsFingerprint" xml:space="preserve">
|
||||
@@ -1465,10 +1464,10 @@
|
||||
<value>Το Bitwarden επιτρέπει να μοιράζεστε τα στοιχεία του vault σας με άλλους χρησιμοποιώντας ένα λογαριασμό οργανισμού. Θέλετε να επισκεφθείτε την ιστοσελίδα bitwarden.com για να μάθετε περισσότερα;</value>
|
||||
</data>
|
||||
<data name="ExportVault" xml:space="preserve">
|
||||
<value>Εξαγωγή του vault</value>
|
||||
<value>Εξαγωγή Vault</value>
|
||||
</data>
|
||||
<data name="LockNow" xml:space="preserve">
|
||||
<value>Κλείδωμα τώρα</value>
|
||||
<value>Κλείδωμα Τώρα</value>
|
||||
</data>
|
||||
<data name="PIN" xml:space="preserve">
|
||||
<value>PIN</value>
|
||||
@@ -1477,7 +1476,7 @@
|
||||
<value>Ξεκλείδωμα</value>
|
||||
</data>
|
||||
<data name="UnlockVault" xml:space="preserve">
|
||||
<value>Ξεκλείδωμα του vault</value>
|
||||
<value>Ξεκλείδωμα Vault</value>
|
||||
</data>
|
||||
<data name="ThirtyMinutes" xml:space="preserve">
|
||||
<value>30 λεπτά</value>
|
||||
@@ -1522,7 +1521,7 @@
|
||||
<value>2 λεπτά</value>
|
||||
</data>
|
||||
<data name="ClearClipboard" xml:space="preserve">
|
||||
<value>Εκκαθάριση πρόχειρου</value>
|
||||
<value>Εκκαθάριση Πρόχειρου</value>
|
||||
<comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment>
|
||||
</data>
|
||||
<data name="ClearClipboardDescription" xml:space="preserve">
|
||||
@@ -1550,7 +1549,7 @@
|
||||
<value>Προεπιλεγμένο σκοτεινό θέμα</value>
|
||||
</data>
|
||||
<data name="CopyNotes" xml:space="preserve">
|
||||
<value>Αντιγραφή σημείωσης</value>
|
||||
<value>Αντιγραφή Σημειώσεων</value>
|
||||
</data>
|
||||
<data name="Exit" xml:space="preserve">
|
||||
<value>Έξοδος</value>
|
||||
@@ -1574,19 +1573,19 @@
|
||||
<comment>'Solarized Dark' is the name of a specific color scheme. It should not be translated.</comment>
|
||||
</data>
|
||||
<data name="AutofillBlockedUris" xml:space="preserve">
|
||||
<value>Αυτόματη συμπλήρωση μπλοκαρισμένων URI</value>
|
||||
<value>Αυτόματη συμπλήρωση μπλοκαρισμένων URIs</value>
|
||||
</data>
|
||||
<data name="AskToAddLogin" xml:space="preserve">
|
||||
<value>Ρωτήστε για να προσθέστε σύνδεση</value>
|
||||
<value>Ζητήστε να προσθέστε σύνδεση</value>
|
||||
</data>
|
||||
<data name="AskToAddLoginDescription" xml:space="preserve">
|
||||
<value>Ρωτήστε για να προσθέσετε ένα αντικείμενο αν δε βρεθεί στο vault σας.</value>
|
||||
<value>Ζητήστε να προσθέσετε ένα αντικείμενο αν δε βρεθεί στην κρύπτη σας.</value>
|
||||
</data>
|
||||
<data name="OnRestart" xml:space="preserve">
|
||||
<value>Κατά την επανεκκίνηση της εφαρμογής</value>
|
||||
<value>Κατά την Επανεκκίνηση Εφαρμογής</value>
|
||||
</data>
|
||||
<data name="AutofillServiceNotEnabled" xml:space="preserve">
|
||||
<value>Η αυτόματη συμπλήρωση διευκολύνει την ασφαλή πρόσβαση στο vault του Bitwarden από άλλες ιστοσελίδες και εφαρμογές. Φαίνεται ότι δεν έχετε ενεργοποιήσει την υπηρεσία αυτόματης συμπλήρωσης για το Bitwarden. Ενεργοποιήστε την αυτόματη συμπλήρωση από τις "Ρυθμίσεις".</value>
|
||||
<value>Η αυτόματη συμπλήρωση διευκολύνει την ασφαλή πρόσβαση στη λίστα από άλλες ιστοσελίδες και εφαρμογές. Φαίνεται ότι δεν έχετε ενεργοποιήσει την υπηρεσία αυτόματης συμπλήρωσης για το Bitwarden. Ενεργοποιήστε την από τις "Ρυθμίσεις".</value>
|
||||
</data>
|
||||
<data name="ThemeAppliedOnRestart" xml:space="preserve">
|
||||
<value>Οι αλλαγές θεμάτων θα ισχύουν όταν γίνει επανεκκίνηση της εφαρμογής.</value>
|
||||
@@ -1596,7 +1595,7 @@
|
||||
<comment>ex. Uppercase the first character of a word.</comment>
|
||||
</data>
|
||||
<data name="IncludeNumber" xml:space="preserve">
|
||||
<value>Συμπερίληψη αριθμών</value>
|
||||
<value>Συμπερίληψη Αριθμών</value>
|
||||
</data>
|
||||
<data name="Download" xml:space="preserve">
|
||||
<value>Λήψη</value>
|
||||
@@ -1611,13 +1610,13 @@
|
||||
<value>Η περίοδος σύνδεσης σας έχει λήξει.</value>
|
||||
</data>
|
||||
<data name="BiometricsDirection" xml:space="preserve">
|
||||
<value>Βιομετρική επαλήθευση</value>
|
||||
<value>Χρήση βιομετρικής μεθόδου για επαλήθευση.</value>
|
||||
</data>
|
||||
<data name="Biometrics" xml:space="preserve">
|
||||
<value>Βιομετρική</value>
|
||||
</data>
|
||||
<data name="UseBiometricsToUnlock" xml:space="preserve">
|
||||
<value>Χρήση βιομετρικών για ξεκλείδωμα</value>
|
||||
<value>Χρήση βιομετρικής μεθόδου για ξεκλείδωμα</value>
|
||||
</data>
|
||||
<data name="AccessibilityOverlayPermissionAlert" xml:space="preserve">
|
||||
<value>Το Bitwarden χρειάζεται προσοχή - Ανατρέξτε στην ενότητα "Υπηρεσία προσβασιμότητας αυτόματης συμπλήρωσης" από τις ρυθμίσεις Bitwarden</value>
|
||||
@@ -1641,7 +1640,7 @@
|
||||
<value>Χορηγήθηκε</value>
|
||||
</data>
|
||||
<data name="FileFormat" xml:space="preserve">
|
||||
<value>Μορφή αρχείου</value>
|
||||
<value>Μορφή Αρχείου</value>
|
||||
</data>
|
||||
<data name="ExportVaultMasterPasswordDescription" xml:space="preserve">
|
||||
<value>Εισαγάγετε τον κύριο κωδικό για εξαγωγή των δεδομένων vault.</value>
|
||||
@@ -1650,7 +1649,7 @@
|
||||
<value>Στείλτε έναν κωδικό επαλήθευσης στο email σας</value>
|
||||
</data>
|
||||
<data name="CodeSent" xml:space="preserve">
|
||||
<value>Ο κωδικός στάλθηκε!</value>
|
||||
<value>Ο Κωδικός Στάλθηκε</value>
|
||||
</data>
|
||||
<data name="ConfirmYourIdentity" xml:space="preserve">
|
||||
<value>Επιβεβαιώστε την ταυτότητα σας για να συνεχίσετε.</value>
|
||||
@@ -1665,7 +1664,7 @@
|
||||
<value>Τα κλειδιά κρυπτογράφησης λογαριασμού είναι μοναδικά για κάθε λογαριασμό χρήστη Bitwarden, οπότε δεν μπορείτε να εισάγετε μια κρυπτογραφημένη εξαγωγή σε διαφορετικό λογαριασμό.</value>
|
||||
</data>
|
||||
<data name="ExportVaultConfirmationTitle" xml:space="preserve">
|
||||
<value>Επιβεβαίωση εξαγωγής vault</value>
|
||||
<value>Επιβεβαίωση εξαγωγής Vault</value>
|
||||
<comment>Title for the alert to confirm vault exports.</comment>
|
||||
</data>
|
||||
<data name="Warning" xml:space="preserve">
|
||||
@@ -1908,7 +1907,7 @@
|
||||
<value>Ημερομηνία διαγραφής</value>
|
||||
</data>
|
||||
<data name="DeletionTime" xml:space="preserve">
|
||||
<value>Χρόνος διαγραφής</value>
|
||||
<value>Χρόνος Διαγραφής</value>
|
||||
</data>
|
||||
<data name="DeletionDateInfo" xml:space="preserve">
|
||||
<value>Το Send θα διαγραφεί οριστικά την καθορισμένη ημερομηνία και ώρα.</value>
|
||||
@@ -1918,7 +1917,7 @@
|
||||
<value>Εκκρεμεί διαγραφή</value>
|
||||
</data>
|
||||
<data name="ExpirationDate" xml:space="preserve">
|
||||
<value>Ημερομηνία λήξης</value>
|
||||
<value>Ημερομηνία Λήξης</value>
|
||||
</data>
|
||||
<data name="ExpirationTime" xml:space="preserve">
|
||||
<value>Χρόνος λήξης</value>
|
||||
@@ -1944,14 +1943,14 @@
|
||||
<value>Τρέχων Αριθμός Πρόσβασης</value>
|
||||
</data>
|
||||
<data name="NewPassword" xml:space="preserve">
|
||||
<value>Νέος κωδικός πρόσβασης</value>
|
||||
<value>Νέος Κωδικός</value>
|
||||
</data>
|
||||
<data name="PasswordInfo" xml:space="preserve">
|
||||
<value>Προαιρετικά απαιτείται κωδικός πρόσβασης για τους χρήστες για να έχουν πρόσβαση σε αυτό το Send.</value>
|
||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||
</data>
|
||||
<data name="RemovePassword" xml:space="preserve">
|
||||
<value>Αφαίρεση κωδικού πρόσβασης</value>
|
||||
<value>Αφαίρεση κωδικού</value>
|
||||
</data>
|
||||
<data name="AreYouSureRemoveSendPassword" xml:space="preserve">
|
||||
<value>Είστε βέβαιοι ότι θέλετε να καταργήσετε τον κωδικό πρόσβασης;</value>
|
||||
@@ -1979,10 +1978,10 @@
|
||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||
</data>
|
||||
<data name="CopyLink" xml:space="preserve">
|
||||
<value>Αντιγραφή συνδέσμου</value>
|
||||
<value>Αντιγραφή Συνδέσμου</value>
|
||||
</data>
|
||||
<data name="ShareLink" xml:space="preserve">
|
||||
<value>Κοινοποίηση συνδέσμου</value>
|
||||
<value>Κοινοποίηση Συνδέσμου</value>
|
||||
</data>
|
||||
<data name="SendLink" xml:space="preserve">
|
||||
<value>Σύνδεσμος Send</value>
|
||||
@@ -2077,7 +2076,7 @@
|
||||
<value>Το Captcha απέτυχε. Παρακαλώ προσπάθησε ξανα.</value>
|
||||
</data>
|
||||
<data name="UpdatedMasterPassword" xml:space="preserve">
|
||||
<value>Ενημερωμένος κύριος κωδικός πρόσβασης</value>
|
||||
<value>Ενημερώθηκε ο κύριος κωδικός πρόσβασης</value>
|
||||
</data>
|
||||
<data name="UpdateMasterPassword" xml:space="preserve">
|
||||
<value>Ενημερώστε τον κύριο κωδικό πρόσβασης</value>
|
||||
@@ -2092,7 +2091,7 @@
|
||||
<value>Δεν είναι δυνατή η ενημέρωση του κωδικού πρόσβασης</value>
|
||||
</data>
|
||||
<data name="RemoveMasterPassword" xml:space="preserve">
|
||||
<value>Αφαίρεση κύριου κωδικού πρόσβασης</value>
|
||||
<value>Αφαίρεση Κύριου Κωδικού Πρόσβασης</value>
|
||||
</data>
|
||||
<data name="RemoveMasterPasswordWarning" xml:space="preserve">
|
||||
<value>{0} χρησιμοποιεί SSO με κρυπτογράφηση διαχείρισης πελατών. Συνεχίζοντας θα καταργήσετε τον Κύριο Κωδικό από το λογαριασμό σας και θα απαιτήσετε SSO για να συνδεθείτε.</value>
|
||||
@@ -2821,7 +2820,7 @@
|
||||
<value>Συνέχεια στην επικοινωνία με την υποστήριξη;</value>
|
||||
</data>
|
||||
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
|
||||
<value>Συνέχεια στην πολιτική απορρήτου;</value>
|
||||
<value>Continue to privacy policy?</value>
|
||||
</data>
|
||||
<data name="ContinueToAppStore" xml:space="preserve">
|
||||
<value>Συνέχεια στο κατάστημα εφαρμογών;</value>
|
||||
@@ -2843,7 +2842,7 @@
|
||||
<value>Δεν μπορείτε να βρείτε αυτό που ψάχνετε; Επικοινωνήστε με την υποστήριξη Bitwarden στο bitwarden.com.</value>
|
||||
</data>
|
||||
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
|
||||
<value>Δείτε την πολιτική απορρήτου μας στο bitwarden.com.</value>
|
||||
<value>Check out our privacy policy on bitwarden.com.</value>
|
||||
</data>
|
||||
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
|
||||
<value>Εξερευνήστε περισσότερες δυνατότητες του Bitwarden λογαριασμού σας, στην εφαρμογή διαδικτύου.</value>
|
||||
@@ -2876,13 +2875,4 @@
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Ρυθμίστε μια επιλογή κλειδώματος για να αλλάξετε την ενέργεια στη λήξη χρόνου του vault σας.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Duo σύνδεση δύο βημάτων απαιτείται για το λογαριασμό σας. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Ακολουθήστε τα βήματα από το Duo για να ολοκληρώσετε τη σύνδεση.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Εκκίνηση Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2876,13 +2876,4 @@ Do you want to switch to this account?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Duo two-step login is required for your account. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Follow the steps from Duo to finish logging in.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Launch Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2890,13 +2890,4 @@ Do you want to switch to this account?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Duo two-step login is required for your account. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Follow the steps from Duo to finish logging in.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Launch Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2823,7 +2823,7 @@ seleccione Agregar TOTP para almacenar la clave de forma segura</value>
|
||||
<value>¿Continuar con el servicio de asistencia?</value>
|
||||
</data>
|
||||
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
|
||||
<value>¿Continuar a la política de privacidad?</value>
|
||||
<value>Continue to privacy policy?</value>
|
||||
</data>
|
||||
<data name="ContinueToAppStore" xml:space="preserve">
|
||||
<value>¿Continuar a la App Store?</value>
|
||||
@@ -2845,7 +2845,7 @@ seleccione Agregar TOTP para almacenar la clave de forma segura</value>
|
||||
<value>¿No encuentras lo que estás buscando? Contacta con el soporte de Bitwarden en bitwarden.com.</value>
|
||||
</data>
|
||||
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
|
||||
<value>Revise nuestra política de privacidad en bitwarden.com.</value>
|
||||
<value>Check out our privacy policy on bitwarden.com.</value>
|
||||
</data>
|
||||
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
|
||||
<value>Explora más características de tu cuenta de Bitwarden en la aplicación web.</value>
|
||||
@@ -2878,13 +2878,4 @@ seleccione Agregar TOTP para almacenar la clave de forma segura</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Configura una opción de desbloqueo para cambiar tu acción de tiempo de espera de tu caja fuerte.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Se requiere el inicio de sesión en dos pasos Duo para su cuenta. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Siga los pasos de Duo para terminar de iniciar sesión.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Iniciar Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2876,13 +2876,4 @@ Soovid selle konto peale lülituda?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Duo two-step login is required for your account. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Follow the steps from Duo to finish logging in.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Launch Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2875,13 +2875,4 @@ Kontu honetara aldatu nahi duzu?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Duo two-step login is required for your account. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Follow the steps from Duo to finish logging in.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Launch Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2877,13 +2877,4 @@
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Duo two-step login is required for your account. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Follow the steps from Duo to finish logging in.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Launch Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -560,7 +560,7 @@
|
||||
<comment>Message shown when interacting with the server</comment>
|
||||
</data>
|
||||
<data name="LoginOrCreateNewAccount" xml:space="preserve">
|
||||
<value>Käytä salattua holviasi kirjautumalla sisään tai luo uusi tili.</value>
|
||||
<value>Käytä salattua holviasi kirjautumalla sisään tai tai luo uusi tili.</value>
|
||||
</data>
|
||||
<data name="Manage" xml:space="preserve">
|
||||
<value>Hallinta</value>
|
||||
@@ -2877,13 +2877,4 @@ Haluatko vaihtaa tähän tiliin?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Muuta holvisi aikakatkaisutoimintoa määrittämällä lukituksen avaustapa.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Tilillesi kirjautuminen vaatii Duo-vahvistuksen.</value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Viimeistele kirjautuminen seuraamalla Duon ohjeita.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Avaa Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2877,13 +2877,4 @@ Gusto mo bang pumunta sa account na ito?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Duo two-step login is required for your account. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Follow the steps from Duo to finish logging in.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Launch Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2877,13 +2877,4 @@ Voulez-vous basculer vers ce compte ?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Configurez une méthode de déverrouillage pour modifier l'action après délai d'expiration de votre coffre.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>L'authentification à deux facteurs Duo est requise pour votre compte. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Follow the steps from Duo to finish logging in.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Lancer Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2877,13 +2877,4 @@ Do you want to switch to this account?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Duo two-step login is required for your account. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Follow the steps from Duo to finish logging in.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Launch Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2879,13 +2879,4 @@ Do you want to switch to this account?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Duo two-step login is required for your account. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Follow the steps from Duo to finish logging in.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Launch Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2876,13 +2876,4 @@ Do you want to switch to this account?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Duo two-step login is required for your account. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Follow the steps from Duo to finish logging in.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Launch Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2874,13 +2874,4 @@
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Za promjenu vremena isteka trezora, odredi način otključavanja.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Duo two-step login is required for your account. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Follow the steps from Duo to finish logging in.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Launch Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2875,13 +2875,4 @@ Szeretnénk átváltani erre a fiókra?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Állítsunk be egy feloldási módot a széf időkifutási műveletének módosításához.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>DUO kétlépéses bejelentkezés szükséges a fiókhoz. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Kövessük a Duo lépéseit a bejelentkezés befejezéséhez.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Duo indítása</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -2876,13 +2876,4 @@ Do you want to switch to this account?</value>
|
||||
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Duo two-step login is required for your account. </value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Follow the steps from Duo to finish logging in.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Launch Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user