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

Compare commits

..

4 Commits

Author SHA1 Message Date
Hinton
4bdbc30873 Dylib 2023-04-27 14:38:32 +02:00
Hinton
39bfda0a24 Add linking instruction everywhere 2023-04-24 15:44:41 +02:00
Hinton
3172b0d571 Use aarch64-apple-ios instead 2023-04-24 15:17:52 +02:00
Hinton
464d1f8a9a test 2023-04-24 14:57:12 +02:00
1162 changed files with 21393 additions and 59277 deletions

46
.github/CODEOWNERS vendored
View File

@@ -1,46 +0,0 @@
# Please sort into logical groups with comment headers. Sort groups in order of specificity.
# For example, default owners should always be the first group.
# Sort lines alphabetically within these groups to avoid accidentally adding duplicates.
#
# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
# Default file owners
* @bitwarden/dept-development-mobile
# DevOps for Actions and other workflow changes
.github/workflows @bitwarden/dept-devops
# DevOps for Version Bumping
src/App/Platforms/Android/AndroidManifest.xml
src/iOS.Autofill/Info.plist
src/iOS.Extension/Info.plist
src/iOS.ShareExtension/Info.plist
src/App/Platforms/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
## Tools team files ##
src/Core/Services/EmailForwarders @bitwarden/team-tools-dev
## Crowdin Sync files ##
src/Core/Resources/Localization @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/watchOS/bitwarden/bitwarden\ WatchKit\ Extension/Localization/en.lproj
store/apple/en
store/google/en
## Utils ##
store/google/Publisher

View File

@@ -1,8 +1,5 @@
blank_issues_enabled: false blank_issues_enabled: false
contact_links: contact_links:
- name: Customer Support
url: https://bitwarden.com/contact/
about: Please contact our customer support for account issues and general customer support.
- name: Report mobile autofill failure - name: Report mobile autofill failure
url: https://docs.google.com/forms/d/e/1FAIpQLScMopHyN7KGJs8hW562VTzbIGL4KcFnx0wJcsW0GYE1BnPiGA/viewform url: https://docs.google.com/forms/d/e/1FAIpQLScMopHyN7KGJs8hW562VTzbIGL4KcFnx0wJcsW0GYE1BnPiGA/viewform
about: We are aware of some situations where the Bitwarden mobile app will not autofill information correctly. This is something the Bitwarden team is actively working on but need your help as a community and active Bitwarden users! about: We are aware of some situations where the Bitwarden mobile app will not autofill information correctly. This is something the Bitwarden team is actively working on but need your help as a community and active Bitwarden users!
@@ -12,6 +9,9 @@ contact_links:
- name: Bitwarden Community Forums - name: Bitwarden Community Forums
url: https://community.bitwarden.com url: https://community.bitwarden.com
about: Please visit the community forums for general community discussion, support and the development roadmap. about: Please visit the community forums for general community discussion, support and the development roadmap.
- name: Customer Support
url: https://bitwarden.com/contact/
about: Please contact our customer support for account issues and general customer support.
- name: Security Issues - name: Security Issues
url: https://hackerone.com/bitwarden url: https://hackerone.com/bitwarden
about: We use HackerOne to manage security disclosures. about: We use HackerOne to manage security disclosures.

19
.github/labeler.yml vendored
View File

@@ -1,19 +0,0 @@
android:
- src/App/*
- src/Core/*
- src/Android/*
iOS:
- src/App/*
- src/Core/*
- lib/ios/*
- src/iOS/*
- 'src/iOS.Autofill/*'
- 'src/iOS.Core/*'
- 'src/iOS.Extension/*'
- 'src/iOS.ShareExtension/*'
- 'src/iOS.Widget/*'
- src/watchOS/*
watchOS:
- src/watchOS/*

56
.github/renovate.json vendored
View File

@@ -1,36 +1,22 @@
{ {
"$schema": "https://docs.renovatebot.com/renovate-schema.json", "$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [ "extends": [
"config:base", "config:base",
"github>bitwarden/renovate-config:pin-actions", "schedule:monthly",
":combinePatchMinorReleases", ":maintainLockFilesMonthly",
":dependencyDashboard", ":preserveSemverRanges",
":maintainLockFilesWeekly", ":rebaseStalePrs",
":pinAllExceptPeerDependencies", ":disableDependencyDashboard"
":prConcurrentLimit10", ],
":rebaseStalePrs", "enabledManagers": [
":separateMajorReleases", "nuget"
"group:monorepos", ],
"schedule:weekends" "packageRules": [
], {
"enabledManagers": ["github-actions", "npm", "nuget"], "matchManagers": ["nuget"],
"commitMessagePrefix": "[deps]:", "groupName": "Nuget updates",
"commitMessageTopic": "{{depName}}", "groupSlug": "nuget",
"packageRules": [ "separateMajorMinor": false
{ }
"groupName": "gh minor", ]
"matchManagers": ["github-actions"], }
"matchUpdateTypes": ["minor", "patch"]
},
{
"groupName": "npm minor",
"matchManagers": ["npm"],
"matchUpdateTypes": ["minor", "patch"]
},
{
"groupName": "nuget minor",
"matchManagers": ["nuget"],
"matchUpdateTypes": ["minor", "patch"]
}
]
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View 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>

Binary file not shown.

BIN
.github/secrets/play_creds.json.gpg vendored Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -14,7 +14,7 @@ jobs:
# Feature request # Feature request
- if: github.event.label.name == 'feature-request' - if: github.event.label.name == 'feature-request'
name: Feature request name: Feature request
uses: peter-evans/close-issue@276d7966e389d888f011539a86c8920025ea0626 # v3.0.1 uses: peter-evans/close-issue@849549ba7c3a595a064c4b2c56f206ee78f93515 # v2.0.0
with: with:
comment: | comment: |
We use GitHub issues as a place to track bugs and other development related issues. The [Bitwarden Community Forums](https://community.bitwarden.com/) has a [Feature Requests](https://community.bitwarden.com/c/feature-requests) section for submitting, voting for, and discussing requests like this one. We use GitHub issues as a place to track bugs and other development related issues. The [Bitwarden Community Forums](https://community.bitwarden.com/) has a [Feature Requests](https://community.bitwarden.com/c/feature-requests) section for submitting, voting for, and discussing requests like this one.
@@ -25,7 +25,7 @@ jobs:
# Intended behavior # Intended behavior
- if: github.event.label.name == 'intended-behavior' - if: github.event.label.name == 'intended-behavior'
name: Intended behaviour name: Intended behaviour
uses: peter-evans/close-issue@276d7966e389d888f011539a86c8920025ea0626 # v3.0.1 uses: peter-evans/close-issue@849549ba7c3a595a064c4b2c56f206ee78f93515 # v2.0.0
with: with:
comment: | comment: |
Your issue appears to be describing the intended behavior of the software. If you want this to be changed, it would be a feature request. Your issue appears to be describing the intended behavior of the software. If you want this to be changed, it would be a feature request.
@@ -38,7 +38,7 @@ jobs:
# Customer support request # Customer support request
- if: github.event.label.name == 'customer-support' - if: github.event.label.name == 'customer-support'
name: Customer Support request name: Customer Support request
uses: peter-evans/close-issue@276d7966e389d888f011539a86c8920025ea0626 # v3.0.1 uses: peter-evans/close-issue@849549ba7c3a595a064c4b2c56f206ee78f93515 # v2.0.0
with: with:
comment: | comment: |
We use GitHub issues as a place to track bugs and other development related issues. Your issue appears to be a support request, or would otherwise be better handled by our dedicated Customer Success team. We use GitHub issues as a place to track bugs and other development related issues. Your issue appears to be a support request, or would otherwise be better handled by our dedicated Customer Success team.
@@ -49,14 +49,14 @@ jobs:
# Resolved # Resolved
- if: github.event.label.name == 'resolved' - if: github.event.label.name == 'resolved'
name: Resolved name: Resolved
uses: peter-evans/close-issue@276d7966e389d888f011539a86c8920025ea0626 # v3.0.1 uses: peter-evans/close-issue@849549ba7c3a595a064c4b2c56f206ee78f93515 # v2.0.0
with: with:
comment: | comment: |
Weve closed this issue, as it appears the original problem has been resolved. If this happens again or continues to be an problem, please respond to this issue with any additional detail to assist with reproduction and root cause analysis. Weve closed this issue, as it appears the original problem has been resolved. If this happens again or continues to be an problem, please respond to this issue with any additional detail to assist with reproduction and root cause analysis.
# Stale # Stale
- if: github.event.label.name == 'stale' - if: github.event.label.name == 'stale'
name: Stale name: Stale
uses: peter-evans/close-issue@276d7966e389d888f011539a86c8920025ea0626 # v3.0.1 uses: peter-evans/close-issue@849549ba7c3a595a064c4b2c56f206ee78f93515 # v2.0.0
with: with:
comment: | comment: |
As we havent heard from you about this problem in some time, this issue will now be closed. As we havent heard from you about this problem in some time, this issue will now be closed.

View File

@@ -1,5 +0,0 @@
---
name: Build Beta
on:
workflow_dispatch:

File diff suppressed because it is too large Load Diff

View File

@@ -15,28 +15,28 @@ jobs:
_CROWDIN_PROJECT_ID: "269690" _CROWDIN_PROJECT_ID: "269690"
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
- name: Login to Azure - CI Subscription - name: Login to Azure
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main uses: bitwarden/gh-actions/get-keyvault-secrets@c3b3285993151c5af47cefcb3b9134c28ab479af
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-prod-kv"
secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase" secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase"
- name: Download translations - name: Download translations
uses: crowdin/github-action@c953b17499daa6be3e5afbf7a63616fb02d8b18d # v1.19.0 uses: crowdin/github-action@12143a68c213f3c6d9913c9e5023224f7231face
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
with: with:
config: crowdin.yml config: crowdin.yml
crowdin_branch_name: main crowdin_branch_name: master
upload_sources: false upload_sources: false
upload_translations: false upload_translations: false
download_translations: true download_translations: true
@@ -48,4 +48,4 @@ jobs:
pull_request_title: "Autosync Crowdin Translations" pull_request_title: "Autosync Crowdin Translations"
pull_request_body: "Autosync the updated translations" pull_request_body: "Autosync the updated translations"
gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }} gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }}
gpg_passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }} gpg_passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }}

View File

@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- name: Enforce Label - name: Enforce Label
uses: yogevbd/enforce-label-action@a3c219da6b8fa73f6ba62b68ff09c469b3a1c024 # 2.2.2 uses: yogevbd/enforce-label-action@8d1e1709b1011e6d90400a0e6cf7c0b77aa5efeb
with: with:
BANNED_LABELS: "hold,needs-qa" BANNED_LABELS: "hold,needs-qa"
BANNED_LABELS_DESCRIPTION: "PRs with the hold or needs-qa labels cannot be merged" BANNED_LABELS_DESCRIPTION: "PRs with the hold or needs-qa labels cannot be merged"

View File

@@ -1,17 +0,0 @@
---
name: "Pull Request Labeler"
on:
pull_request_target: {}
jobs:
labeler:
name: "Pull Request Labeler"
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-20.04
steps:
- uses: actions/labeler@ac9175f8a1f3625fd0d4fb234536d26811351594 # v4.3.0
with:
sync-labels: true

View File

@@ -28,7 +28,7 @@ jobs:
branch-name: ${{ steps.branch.outputs.branch-name }} branch-name: ${{ steps.branch.outputs.branch-name }}
steps: steps:
- name: Branch check - name: Branch check
if: inputs.release_type != 'Dry Run' if: github.event.inputs.release_type != 'Dry Run'
run: | run: |
if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then
echo "===================================" echo "==================================="
@@ -38,15 +38,15 @@ jobs:
fi fi
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2.4.0
- name: Check Release Version - name: Check Release Version
id: version id: version
uses: bitwarden/gh-actions/release-version-check@main uses: bitwarden/gh-actions/release-version-check@8f055ef543c7433c967a1b9b04a0f230923233bb
with: with:
release-type: ${{ inputs.release_type }} release-type: ${{ github.event.inputs.release_type }}
project-type: xamarin project-type: xamarin
file: src/App/Platforms/Android/AndroidManifest.xml file: src/Android/Properties/AndroidManifest.xml
- name: Get branch name - name: Get branch name
id: branch id: branch
@@ -55,8 +55,8 @@ jobs:
echo "branch-name=$BRANCH_NAME" >> $GITHUB_OUTPUT echo "branch-name=$BRANCH_NAME" >> $GITHUB_OUTPUT
- name: Create GitHub deployment - name: Create GitHub deployment
if: ${{ inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: chrnorm/deployment-action@55729fcebec3d284f60f5bcabbd8376437d696b1 # v2.0.7 uses: chrnorm/deployment-action@1b599fe41a0ef1f95191e7f2eec4743f2d7dfc48
id: deployment id: deployment
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
@@ -67,27 +67,27 @@ jobs:
- name: Download all artifacts - name: Download all artifacts
if: ${{ inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2 uses: dawidd6/action-download-artifact@575b1e4167df67acf7e692af784566618b23c71e # v2.17.10
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
branch: ${{ steps.branch.outputs.branch-name }} branch: ${{ steps.branch.outputs.branch-name }}
- name: Dry Run - Download all artifacts - name: Dry Run - Download all artifacts
if: ${{ inputs.release_type == 'Dry Run' }} if: ${{ github.event.inputs.release_type == 'Dry Run' }}
uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2 uses: dawidd6/action-download-artifact@575b1e4167df67acf7e692af784566618b23c71e # v2.17.10
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
branch: main branch: master
- name: Prep Bitwarden iOS release asset - name: Prep Bitwarden iOS release asset
run: zip -r Bitwarden\ iOS.zip Bitwarden\ iOS run: zip -r Bitwarden\ iOS.zip Bitwarden\ iOS
- name: Create release - name: Create release
if: ${{ inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0 uses: ncipollo/release-action@40bb172bd05f266cf9ba4ff965cb61e9ee5f6d01 # v1.9.0
with: with:
artifacts: "./com.x8bit.bitwarden.aab/com.x8bit.bitwarden.aab, artifacts: "./com.x8bit.bitwarden.aab/com.x8bit.bitwarden.aab,
./com.x8bit.bitwarden.apk/com.x8bit.bitwarden.apk, ./com.x8bit.bitwarden.apk/com.x8bit.bitwarden.apk,
@@ -103,16 +103,16 @@ jobs:
draft: true draft: true
- name: Update deployment status to Success - name: Update deployment status to Success
if: ${{ inputs.release_type != 'Dry Run' && success() }} if: ${{ github.event.inputs.release_type != 'Dry Run' && success() }}
uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3 uses: chrnorm/deployment-status@07b3930847f65e71c9c6802ff5a402f6dfb46b86
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
state: 'success' state: 'success'
deployment-id: ${{ steps.deployment.outputs.deployment_id }} deployment-id: ${{ steps.deployment.outputs.deployment_id }}
- name: Update deployment status to Failure - name: Update deployment status to Failure
if: ${{ inputs.release_type != 'Dry Run' && failure() }} if: ${{ github.event.inputs.release_type != 'Dry Run' && failure() }}
uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3 uses: chrnorm/deployment-status@07b3930847f65e71c9c6802ff5a402f6dfb46b86
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
state: 'failure' state: 'failure'
@@ -126,11 +126,11 @@ jobs:
if: inputs.fdroid_publish if: inputs.fdroid_publish
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2.4.0
- name: Download F-Droid .apk artifact - name: Download F-Droid .apk artifact
if: ${{ inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2 uses: dawidd6/action-download-artifact@575b1e4167df67acf7e692af784566618b23c71e # v2.17.10
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
@@ -138,18 +138,18 @@ jobs:
name: com.x8bit.bitwarden-fdroid.apk name: com.x8bit.bitwarden-fdroid.apk
- name: Dry Run - Download F-Droid .apk artifact - name: Dry Run - Download F-Droid .apk artifact
if: ${{ inputs.release_type == 'Dry Run' }} if: ${{ github.event.inputs.release_type == 'Dry Run' }}
uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2 uses: dawidd6/action-download-artifact@575b1e4167df67acf7e692af784566618b23c71e # v2.17.10
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
branch: main branch: master
name: com.x8bit.bitwarden-fdroid.apk name: com.x8bit.bitwarden-fdroid.apk
- name: Set up Node - name: Set up Node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561 # v2.5.1
with: with:
node-version: '16.x' node-version: '10.x'
- name: Set up F-Droid server - name: Set up F-Droid server
run: | run: |
@@ -176,19 +176,13 @@ jobs:
- name: Install Node dependencies - name: Install Node dependencies
run: npm install run: npm install
- name: Login to Azure - CI Subscription - name: Decrypt secrets
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Download secrets
env: env:
ACCOUNT_NAME: bitwardenci DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }}
CONTAINER_NAME: mobile
run: | run: |
mkdir -p $HOME/secrets mkdir -p ~/secrets
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \ gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--name store_fdroid-keystore.jks --file ./store/fdroid/keystore.jks --output none --output ./store/fdroid/keystore.jks ./.github/secrets/store_fdroid-keystore.jks.gpg
- name: Compile for F-Droid Store - name: Compile for F-Droid Store
env: env:
@@ -217,5 +211,5 @@ jobs:
cd $GITHUB_WORKSPACE cd $GITHUB_WORKSPACE
- name: Deploy to gh-pages - name: Deploy to gh-pages
if: ${{ inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
run: npm run deploy run: npm run deploy

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- name: 'Run stale action' - name: 'Run stale action'
uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0 uses: actions/stale@3cc123766321e9f15a6676375c154ccffb12a358 # v5.0.0
with: with:
stale-issue-label: 'needs-reply' stale-issue-label: 'needs-reply'
stale-pr-label: 'needs-changes' stale-pr-label: 'needs-changes'
@@ -27,4 +27,4 @@ jobs:
If youre still working on this, please respond here after youve made the changes weve requested and our team will re-open it for further review. If youre still working on this, please respond here after youve made the changes weve requested and our team will re-open it for further review.
Please make sure to resolve any conflicts with the main branch before requesting another review. Please make sure to resolve any conflicts with the master branch before requesting another review.

View File

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

View File

@@ -1,54 +1,42 @@
--- ---
name: Version Bump name: Version Bump
run-name: Version Bump - v${{ inputs.version_number }}
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
version_number: version_number:
description: "New version (example: '2024.1.0')" description: "New Version"
required: true
workflow_call:
inputs:
version_number:
required: true
secrets:
AZURE_PROD_KV_CREDENTIALS:
required: true required: true
cut_rc_branch:
description: "Cut RC branch?"
default: true
type: boolean
jobs: jobs:
bump_version: bump_version:
name: "Bump Version to v${{ inputs.version_number }}" name: "Create version_bump_${{ github.event.inputs.version_number }} branch"
runs-on: ubuntu-22.04 runs-on: ubuntu-20.04
steps: steps:
- name: Login to Azure - CI Subscription - name: Checkout Branch
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Login to Azure - Prod Subscription
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main uses: bitwarden/gh-actions/get-keyvault-secrets@c3b3285993151c5af47cefcb3b9134c28ab479af
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-prod-kv"
secrets: "github-gpg-private-key, secrets: "github-gpg-private-key, github-gpg-private-key-passphrase"
github-gpg-private-key-passphrase,
github-pat-bitwarden-devops-bot-repo-scope"
- name: Checkout Branch
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: main
- name: Check if RC branch exists
if: ${{ inputs.cut_rc_branch == true }}
run: |
remote_rc_branch_check=$(git ls-remote --heads origin rc | wc -l)
if [[ "${remote_rc_branch_check}" -gt 0 ]]; then
echo "Remote RC branch exists."
echo "Please delete current RC branch before running again."
exit 1
fi
- name: Import GPG key - name: Import GPG key
uses: crazy-max/ghaction-import-gpg@01dd5d3ca463c7f10f7f4f7b4f177225ac661ee4 # v6.1.0 uses: crazy-max/ghaction-import-gpg@c8bb57c57e8df1be8c73ff3d59deab1dbc00e0d1
with: with:
gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }} gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }}
passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }} passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }}
@@ -56,68 +44,37 @@ jobs:
git_commit_gpgsign: true git_commit_gpgsign: true
- name: Create Version Branch - name: Create Version Branch
id: create-branch run: git switch -c version_bump_${{ github.event.inputs.version_number }}
run: |
NAME=version_bump_${{ github.ref_name }}_${{ inputs.version_number }}
git switch -c $NAME
echo "name=$NAME" >> $GITHUB_OUTPUT
- name: Install xmllint
run: sudo apt install -y libxml2-utils
- name: Verify input version
env:
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."
exit 1
fi
# Check if version is newer.
printf '%s\n' "${CURRENT_VERSION}" "${NEW_VERSION}" | sort -C -V
if [ $? -eq 0 ]; then
echo "Version check successful."
else
echo "Version check failed."
exit 1
fi
- name: Bump Version - Android XML - name: Bump Version - Android XML
uses: bitwarden/gh-actions/version-bump@main uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945
with: with:
version: ${{ inputs.version_number }} version: ${{ github.event.inputs.version_number }}
file_path: "src/App/Platforms/Android/AndroidManifest.xml" file_path: "./src/Android/Properties/AndroidManifest.xml"
- name: Bump Version - iOS.Autofill - name: Bump Version - iOS.Autofill
uses: bitwarden/gh-actions/version-bump@main uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945
with: with:
version: ${{ inputs.version_number }} version: ${{ github.event.inputs.version_number }}
file_path: "src/iOS.Autofill/Info.plist" file_path: "./src/iOS.Autofill/Info.plist"
- name: Bump Version - iOS.Extension - name: Bump Version - iOS.Extension
uses: bitwarden/gh-actions/version-bump@main uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945
with: with:
version: ${{ inputs.version_number }} version: ${{ github.event.inputs.version_number }}
file_path: "src/iOS.Extension/Info.plist" file_path: "./src/iOS.Extension/Info.plist"
- name: Bump Version - iOS.ShareExtension - name: Bump Version - iOS.ShareExtension
uses: bitwarden/gh-actions/version-bump@main uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945
with: with:
version: ${{ inputs.version_number }} version: ${{ github.event.inputs.version_number }}
file_path: "src/iOS.ShareExtension/Info.plist" file_path: "./src/iOS.ShareExtension/Info.plist"
- name: Bump Version - iOS - name: Bump Version - iOS
uses: bitwarden/gh-actions/version-bump@main uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945
with: with:
version: ${{ inputs.version_number }} version: ${{ github.event.inputs.version_number }}
file_path: "src/App/Platforms/iOS/Info.plist" file_path: "./src/iOS/Info.plist"
- name: Setup git - name: Setup git
run: | run: |
@@ -136,24 +93,22 @@ jobs:
- name: Commit files - name: Commit files
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }} if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
run: git commit -m "Bumped version to ${{ inputs.version_number }}" -a run: git commit -m "Bumped version to ${{ github.event.inputs.version_number }}" -a
- name: Push changes - name: Push changes
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }} if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
env: run: git push -u origin version_bump_${{ github.event.inputs.version_number }}
PR_BRANCH: ${{ steps.create-branch.outputs.name }}
run: git push -u origin $PR_BRANCH
- name: Create Version PR - name: Create Version PR
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }} if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
id: create-pr
env: env:
GH_TOKEN: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }} PR_BRANCH: "version_bump_${{ github.event.inputs.version_number }}"
PR_BRANCH: ${{ steps.create-branch.outputs.name }} GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
TITLE: "Bump version to ${{ inputs.version_number }}" BASE_BRANCH: master
TITLE: "Bump version to ${{ github.event.inputs.version_number }}"
run: | run: |
PR_URL=$(gh pr create --title "$TITLE" \ gh pr create --title "$TITLE" \
--base "main" \ --base "$BASE" \
--head "$PR_BRANCH" \ --head "$PR_BRANCH" \
--label "version update" \ --label "version update" \
--label "automated pr" \ --label "automated pr" \
@@ -166,54 +121,4 @@ jobs:
- [X] Other - [X] Other
## Objective ## Objective
Automated version bump to ${{ inputs.version_number }}") Automated version bump to ${{ github.event.inputs.version_number }}"
echo "pr_number=${PR_URL##*/}" >> $GITHUB_OUTPUT
- name: Approve PR
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }}
run: gh pr review $PR_NUMBER --approve
- name: Merge PR
env:
GH_TOKEN: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }}
run: gh pr merge $PR_NUMBER --squash --auto --delete-branch
cut_rc:
name: Cut RC branch
needs: bump_version
if: ${{ inputs.cut_rc_branch == true }}
runs-on: ubuntu-22.04
steps:
- name: Checkout Branch
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: main
- name: Install xmllint
run: sudo apt install -y libxml2-utils
- name: Verify version has been updated
env:
NEW_VERSION: ${{ inputs.version_number }}
run: |
# Wait for version to change.
while : ; do
echo "Waiting for version to be updated..."
git pull --force
CURRENT_VERSION=$(xmllint --xpath '
string(/manifest/@*[local-name()="versionName"
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
- name: Cut RC branch
run: |
git switch --quiet --create rc
git push --quiet --set-upstream origin rc

11
.github/workflows/workflow-linter.yml vendored Normal file
View 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@master

1
.gitignore vendored
View File

@@ -31,7 +31,6 @@ Components/
x64/ x64/
x86/ x86/
!src/lib/x86/ !src/lib/x86/
!src/App/Platforms/Android/lib/x86/
build/ build/
bld/ bld/
[Bb]in/ [Bb]in/

View File

@@ -1,16 +0,0 @@
<Project>
<PropertyGroup>
<MauiVersion>8.0.7</MauiVersion>
<ReleaseCodesignProvision>Automatic:AppStore</ReleaseCodesignProvision>
<ReleaseCodesignKey>iPhone Distribution</ReleaseCodesignKey>
<IncludeBitwardeniOSExtensions>True</IncludeBitwardeniOSExtensions>
<IncludeBitwardenWatchOSApp>True</IncludeBitwardenWatchOSApp>
<Argon2IdLoadMtouchExtraArgs>-gcc_flags "-L$(ProjectDir)../../lib/ios -largon2 -force_load $(ProjectDir)../../lib/ios/libargon2.a"</Argon2IdLoadMtouchExtraArgs>
<!-- Uncomment this when Unit Testing-->
<!-- <CustomConstants>UT</CustomConstants> -->
<!-- Uncomment this when building FDROID-->
<!-- <CustomConstants>FDROID</CustomConstants> -->
</PropertyGroup>
</Project>

View File

@@ -1,12 +1,12 @@
[![Github Workflow build on main](https://github.com/bitwarden/mobile/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/bitwarden/mobile/actions/workflows/build.yml?query=branch:main) [![Github Workflow build on master](https://github.com/bitwarden/mobile/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/bitwarden/mobile/actions/workflows/build.yml?query=branch:master)
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/bitwarden-mobile/localized.svg)](https://crowdin.com/project/bitwarden-mobile) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/bitwarden-mobile/localized.svg)](https://crowdin.com/project/bitwarden-mobile)
[![Join the chat at https://gitter.im/bitwarden/Lobby](https://badges.gitter.im/bitwarden/Lobby.svg)](https://gitter.im/bitwarden/Lobby) [![Join the chat at https://gitter.im/bitwarden/Lobby](https://badges.gitter.im/bitwarden/Lobby.svg)](https://gitter.im/bitwarden/Lobby)
# Bitwarden Mobile Application # Bitwarden Mobile Application
<a href="https://play.google.com/store/apps/details?id=com.x8bit.bitwarden" target="_blank"><img alt="Get it on Google Play" src="https://imgur.com/YQzmZi9.png" width="153" height="46"></a> <a href="https://mobileapp.bitwarden.com/fdroid/" target="_blank"><img alt="Get it on F-Droid" src="https://i.imgur.com/HDicnzz.png" width="154" height="46"></a> <a href="https://itunes.apple.com/us/app/bitwarden-free-password-manager/id1137397744?mt=8" target="_blank"><img src="https://imgur.com/GdGqPMY.png" width="135" height="40"></a> <a href="https://play.google.com/store/apps/details?id=com.x8bit.bitwarden" target="_blank"><img alt="Get it on Google Play" src="https://imgur.com/YQzmZi9.png" width="153" height="46"></a> <a href="https://mobileapp.bitwarden.com/fdroid/" target="_blank"><img alt="Get it on Google Play" src="https://i.imgur.com/HDicnzz.png" width="154" height="46"></a> <a href="https://itunes.apple.com/us/app/bitwarden-free-password-manager/id1137397744?mt=8" target="_blank"><img src="https://imgur.com/GdGqPMY.png" width="135" height="40"></a>
The Bitwarden mobile application is written in C# using .NET MAUI. The Bitwarden mobile application is written in C# with Xamarin Android, Xamarin iOS, and Xamarin Forms.
<img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/mobile-android-myvault.png" alt="" width="325" height="650" /> <img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/mobile-ios-myvault.png" alt="" width="300" height="650" /> <img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/mobile-android-myvault.png" alt="" width="325" height="650" /> <img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/mobile-ios-myvault.png" alt="" width="300" height="650" />
@@ -20,6 +20,6 @@ Interested in contributing in a big way? Consider joining our team! We're hiring
# Contribute # Contribute
Code contributions are welcome! Please commit any pull requests against the `main` branch. Learn more about how to contribute by reading the [Contributing Guidelines](https://contributing.bitwarden.com/contributing/). Check out the [Contributing Documentation](https://contributing.bitwarden.com/) for how to get started with your first contribution. Code contributions are welcome! Please commit any pull requests against the `master` branch. Learn more about how to contribute by reading the [Contributing Guidelines](https://contributing.bitwarden.com/contributing/). Check out the [Contributing Documentation](https://contributing.bitwarden.com/) for how to get started with your first contribution.
Security audits and feedback are welcome. Please open an issue or email us privately if the report is sensitive in nature. You can read our security policy in the [`SECURITY.md`](SECURITY.md) file. Security audits and feedback are welcome. Please open an issue or email us privately if the report is sensitive in nature. You can read our security policy in the [`SECURITY.md`](SECURITY.md) file.

View File

@@ -1,233 +1,471 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 16
VisualStudioVersion = 17.8.34112.27 VisualStudioVersion = 16.0.29009.5
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "App", "src\App\App.csproj", "{971FDF07-E288-4239-B47A-E9E7E912193B}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Android", "src\Android\Android.csproj", "{304400AF-F0ED-40FA-B102-EA3C3EC43E4F}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "src\Core\Core.csproj", "{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App", "src\App\App.csproj", "{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "iOS.Core", "src\iOS.Core\iOS.Core.csproj", "{E71F3053-056C-4381-9638-048ED73BDFF6}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core", "src\Core\Core.csproj", "{4B8A8C41-9820-4341-974C-41E65B7F4366}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Playground", "test\Playground\Playground.csproj", "{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{D10CA4A9-F866-40E1-B658-F69051236C71}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{8904C536-C67D-420F-9971-51B26574C3AA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "store", "store", "{92470CBD-9047-4C3C-8EA3-D972D6622D84}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "google", "google", "{2E399654-26A2-46F6-B9CA-1B496A3F370A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{76690DFB-B7F4-4781-83E4-113FDC450AFE}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.gitignore = .gitignore
.github\workflows\build.yml = .github\workflows\build.yml
CONTRIBUTING.md = CONTRIBUTING.md
crowdin.yml = crowdin.yml
README.md = README.md
SECURITY.md = SECURITY.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Publisher", "store\google\Publisher\Publisher.csproj", "{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.Core", "src\iOS.Core\iOS.Core.csproj", "{E71F3053-056C-4381-9638-048ED73BDFF6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS", "src\iOS\iOS.csproj", "{599E0201-420A-4C3E-A7BA-5349F72E0B15}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.Extension", "src\iOS.Extension\iOS.Extension.csproj", "{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.Extension", "src\iOS.Extension\iOS.Extension.csproj", "{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "test\Common\Common.csproj", "{4085B0A5-12A9-4993-B8B8-4ACE72E62E39}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.Test", "test\Core.Test\Core.Test.csproj", "{8AE548D9-A567-4E97-995E-93EC7DB0FDE0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.ShareExtension", "src\iOS.ShareExtension\iOS.ShareExtension.csproj", "{F8C3F648-EA5A-4719-8005-85D1690B1655}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.ShareExtension", "src\iOS.ShareExtension\iOS.ShareExtension.csproj", "{F8C3F648-EA5A-4719-8005-85D1690B1655}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.Autofill", "src\iOS.Autofill\iOS.Autofill.csproj", "{83449CC4-1F76-4CFE-92B1-D2E13A62506F}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.Autofill", "src\iOS.Autofill\iOS.Autofill.csproj", "{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{BB702EBD-3B79-4ECA-A2A6-1237B07F0AF0}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B972BBFA-917F-4A10-B07E-B89CFEC6BBDC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.Test", "test\Core.Test\Core.Test.csproj", "{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "test\Common\Common.csproj", "{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
Release|Any CPU = Release|Any CPU
Debug|iPhoneSimulator = Debug|iPhoneSimulator
Release|iPhoneSimulator = Release|iPhoneSimulator
Debug|iPhone = Debug|iPhone
Release|iPhone = Release|iPhone
AppStore|iPhoneSimulator = AppStore|iPhoneSimulator
AppStore|iPhone = AppStore|iPhone
Ad-Hoc|iPhoneSimulator = Ad-Hoc|iPhoneSimulator
Ad-Hoc|iPhone = Ad-Hoc|iPhone Ad-Hoc|iPhone = Ad-Hoc|iPhone
Ad-Hoc|iPhoneSimulator = Ad-Hoc|iPhoneSimulator
AppStore|Any CPU = AppStore|Any CPU
AppStore|iPhone = AppStore|iPhone
AppStore|iPhoneSimulator = AppStore|iPhoneSimulator
Debug|Any CPU = Debug|Any CPU
Debug|iPhone = Debug|iPhone
Debug|iPhoneSimulator = Debug|iPhoneSimulator
FDroid|Any CPU = FDroid|Any CPU FDroid|Any CPU = FDroid|Any CPU
FDroid|iPhone = FDroid|iPhone
FDroid|iPhoneSimulator = FDroid|iPhoneSimulator
Release|Any CPU = Release|Any CPU
Release|iPhone = Release|iPhone
Release|iPhoneSimulator = Release|iPhoneSimulator
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{971FDF07-E288-4239-B47A-E9E7E912193B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.Debug|Any CPU.Build.0 = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Ad-Hoc|Any CPU.Deploy.0 = Release|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.Release|Any CPU.ActiveCfg = Release|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.Release|Any CPU.Build.0 = Release|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.Release|Any CPU.Deploy.0 = Release|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Ad-Hoc|iPhone.Deploy.0 = Release|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Ad-Hoc|iPhoneSimulator.Deploy.0 = Release|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.Debug|iPhone.ActiveCfg = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.AppStore|Any CPU.Build.0 = Release|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.Debug|iPhone.Build.0 = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.AppStore|Any CPU.Deploy.0 = Release|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.Release|iPhone.ActiveCfg = Release|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.AppStore|iPhone.ActiveCfg = Release|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.Release|iPhone.Build.0 = Release|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.AppStore|iPhone.Build.0 = Release|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.AppStore|iPhone.Deploy.0 = Release|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.AppStore|iPhone.ActiveCfg = Release|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.AppStore|iPhone.Build.0 = Release|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.AppStore|iPhoneSimulator.Deploy.0 = Release|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.FDroid|Any CPU.ActiveCfg = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Debug|iPhone.Build.0 = Debug|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.FDroid|Any CPU.Build.0 = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Debug|iPhone.Deploy.0 = Debug|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Debug|Any CPU.Build.0 = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Release|Any CPU.ActiveCfg = Release|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Release|Any CPU.Build.0 = Release|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.FDroid|Any CPU.ActiveCfg = FDroid|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.FDroid|Any CPU.Build.0 = FDroid|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.FDroid|Any CPU.Deploy.0 = FDroid|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.FDroid|iPhone.ActiveCfg = FDroid|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.FDroid|iPhone.Build.0 = FDroid|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Debug|iPhone.ActiveCfg = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.FDroid|iPhone.Deploy.0 = FDroid|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Debug|iPhone.Build.0 = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.FDroid|iPhoneSimulator.ActiveCfg = FDroid|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Release|iPhone.ActiveCfg = Release|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.FDroid|iPhoneSimulator.Build.0 = FDroid|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Release|iPhone.Build.0 = Release|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.FDroid|iPhoneSimulator.Deploy.0 = FDroid|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Release|Any CPU.Build.0 = Release|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.AppStore|iPhone.ActiveCfg = Release|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Release|Any CPU.Deploy.0 = Release|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.AppStore|iPhone.Build.0 = Release|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Release|iPhone.ActiveCfg = Release|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Release|iPhone.Build.0 = Release|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Release|iPhone.Deploy.0 = Release|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.FDroid|Any CPU.ActiveCfg = Debug|Any CPU {304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.FDroid|Any CPU.Build.0 = Debug|Any CPU {EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|Any CPU.Deploy.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|iPhone.Deploy.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|iPhoneSimulator.Deploy.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|Any CPU.Build.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|Any CPU.Deploy.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|iPhone.ActiveCfg = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|iPhone.Build.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|iPhone.Deploy.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|iPhoneSimulator.Deploy.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Debug|iPhone.Build.0 = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Debug|iPhone.Deploy.0 = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.FDroid|Any CPU.ActiveCfg = FDroid|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.FDroid|Any CPU.Build.0 = FDroid|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.FDroid|iPhone.ActiveCfg = FDroid|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.FDroid|iPhone.Build.0 = FDroid|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.FDroid|iPhoneSimulator.ActiveCfg = FDroid|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.FDroid|iPhoneSimulator.Build.0 = FDroid|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Release|Any CPU.Build.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Release|Any CPU.Deploy.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Release|iPhone.ActiveCfg = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Release|iPhone.Build.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Release|iPhone.Deploy.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.AppStore|Any CPU.Build.0 = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.AppStore|iPhone.ActiveCfg = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.AppStore|iPhone.Build.0 = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Debug|iPhone.Build.0 = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.FDroid|Any CPU.ActiveCfg = FDroid|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.FDroid|Any CPU.Build.0 = FDroid|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.FDroid|iPhone.ActiveCfg = FDroid|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.FDroid|iPhone.Build.0 = FDroid|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.FDroid|iPhoneSimulator.ActiveCfg = FDroid|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.FDroid|iPhoneSimulator.Build.0 = FDroid|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Release|Any CPU.Build.0 = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Release|iPhone.ActiveCfg = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Release|iPhone.Build.0 = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.AppStore|iPhone.Build.0 = Debug|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.Debug|iPhone.Build.0 = Debug|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.FDroid|Any CPU.ActiveCfg = FDroid|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.FDroid|Any CPU.Build.0 = FDroid|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.FDroid|iPhone.ActiveCfg = FDroid|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.FDroid|iPhone.Build.0 = FDroid|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.FDroid|iPhoneSimulator.ActiveCfg = FDroid|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.FDroid|iPhoneSimulator.Build.0 = FDroid|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.Release|Any CPU.Build.0 = Release|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.Release|iPhone.ActiveCfg = Release|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.Release|iPhone.Build.0 = Release|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.AppStore|iPhone.Build.0 = Debug|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Debug|iPhone.Build.0 = Debug|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.FDroid|Any CPU.ActiveCfg = FDroid|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.FDroid|Any CPU.Build.0 = FDroid|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.FDroid|iPhone.ActiveCfg = FDroid|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.FDroid|iPhone.Build.0 = FDroid|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.FDroid|iPhoneSimulator.ActiveCfg = FDroid|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.FDroid|iPhoneSimulator.Build.0 = FDroid|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Release|Any CPU.Build.0 = Release|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Release|iPhone.ActiveCfg = Release|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Release|iPhone.Build.0 = Release|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|Any CPU.Build.0 = Ad-Hoc|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|Any CPU.ActiveCfg = AppStore|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|Any CPU.Build.0 = AppStore|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhone.Build.0 = AppStore|iPhone
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|Any CPU.Build.0 = Debug|Any CPU {E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|iPhone.ActiveCfg = Debug|iPhone
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|iPhone.Build.0 = Debug|iPhone
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{E71F3053-056C-4381-9638-048ED73BDFF6}.FDroid|Any CPU.ActiveCfg = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.FDroid|Any CPU.Build.0 = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.FDroid|iPhone.ActiveCfg = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.FDroid|iPhone.Build.0 = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.FDroid|iPhoneSimulator.ActiveCfg = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.FDroid|iPhoneSimulator.Build.0 = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Release|Any CPU.ActiveCfg = Release|Any CPU {E71F3053-056C-4381-9638-048ED73BDFF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Release|Any CPU.Build.0 = Release|Any CPU {E71F3053-056C-4381-9638-048ED73BDFF6}.Release|Any CPU.Build.0 = Release|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|iPhone.Build.0 = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Release|iPhone.ActiveCfg = Release|Any CPU {E71F3053-056C-4381-9638-048ED73BDFF6}.Release|iPhone.ActiveCfg = Release|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Release|iPhone.Build.0 = Release|Any CPU {E71F3053-056C-4381-9638-048ED73BDFF6}.Release|iPhone.Build.0 = Release|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU {E71F3053-056C-4381-9638-048ED73BDFF6}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU {E71F3053-056C-4381-9638-048ED73BDFF6}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhone.ActiveCfg = Release|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhone.Build.0 = Release|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.AppStore|Any CPU.ActiveCfg = AppStore|iPhone
{E71F3053-056C-4381-9638-048ED73BDFF6}.FDroid|Any CPU.ActiveCfg = Debug|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
{E71F3053-056C-4381-9638-048ED73BDFF6}.FDroid|Any CPU.Build.0 = Debug|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.AppStore|iPhone.Build.0 = AppStore|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|Any CPU.Build.0 = Debug|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|Any CPU.ActiveCfg = Release|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.Debug|Any CPU.ActiveCfg = Debug|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|Any CPU.Build.0 = Release|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.Debug|iPhone.ActiveCfg = Debug|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.Debug|iPhone.Build.0 = Debug|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.Debug|iPhone.Deploy.0 = Debug|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|iPhone.ActiveCfg = Debug|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.FDroid|Any CPU.ActiveCfg = FDroid|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|iPhone.Build.0 = Debug|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.FDroid|iPhone.ActiveCfg = FDroid|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|iPhone.ActiveCfg = Release|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.FDroid|iPhone.Build.0 = FDroid|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|iPhone.Build.0 = Release|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.FDroid|iPhoneSimulator.ActiveCfg = FDroid|iPhoneSimulator
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.FDroid|iPhoneSimulator.Build.0 = FDroid|iPhoneSimulator
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.Release|Any CPU.ActiveCfg = Release|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.AppStore|iPhone.ActiveCfg = Release|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.Release|iPhone.ActiveCfg = Release|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.AppStore|iPhone.Build.0 = Release|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.Release|iPhone.Build.0 = Release|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU {599E0201-420A-4C3E-A7BA-5349F72E0B15}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|Any CPU.Build.0 = Ad-Hoc|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.FDroid|Any CPU.ActiveCfg = Debug|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.FDroid|Any CPU.Build.0 = Debug|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|Any CPU.Build.0 = Debug|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|Any CPU.ActiveCfg = Release|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.AppStore|Any CPU.ActiveCfg = AppStore|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|Any CPU.Build.0 = Release|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.AppStore|Any CPU.Build.0 = AppStore|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.AppStore|iPhone.Build.0 = AppStore|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|iPhone.ActiveCfg = Debug|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|Any CPU.ActiveCfg = Debug|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|iPhone.Build.0 = Debug|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|iPhone.ActiveCfg = Debug|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|iPhone.ActiveCfg = Release|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|iPhone.Build.0 = Debug|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|iPhone.Build.0 = Release|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|iPhone.Deploy.0 = Debug|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.AppStore|iPhone.ActiveCfg = Release|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.FDroid|Any CPU.ActiveCfg = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.AppStore|iPhone.Build.0 = Release|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.FDroid|Any CPU.Build.0 = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.FDroid|iPhone.ActiveCfg = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.FDroid|iPhone.Build.0 = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.FDroid|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.FDroid|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.FDroid|Any CPU.ActiveCfg = Debug|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|Any CPU.ActiveCfg = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.FDroid|Any CPU.Build.0 = Debug|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|iPhone.ActiveCfg = Release|iPhone
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|iPhone.Build.0 = Release|iPhone
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.Debug|Any CPU.Build.0 = Debug|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.Release|Any CPU.ActiveCfg = Release|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.Release|Any CPU.Build.0 = Release|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.Release|iPhone.ActiveCfg = Release|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.Release|iPhone.Build.0 = Release|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.AppStore|iPhone.ActiveCfg = Release|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.AppStore|iPhone.Build.0 = Release|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.AppStore|Any CPU.Build.0 = Release|Any CPU
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.AppStore|iPhone.ActiveCfg = Release|Any CPU
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.FDroid|Any CPU.ActiveCfg = Debug|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.AppStore|iPhone.Build.0 = Release|Any CPU
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.FDroid|Any CPU.Build.0 = Debug|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Debug|Any CPU.Build.0 = Debug|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Release|Any CPU.ActiveCfg = Release|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Debug|Any CPU.Build.0 = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Release|Any CPU.Build.0 = Release|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Debug|iPhone.Build.0 = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.FDroid|Any CPU.ActiveCfg = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Debug|iPhone.ActiveCfg = Debug|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.FDroid|Any CPU.Build.0 = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Debug|iPhone.Build.0 = Debug|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.FDroid|iPhone.ActiveCfg = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Release|iPhone.ActiveCfg = Release|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.FDroid|iPhone.Build.0 = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Release|iPhone.Build.0 = Release|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.FDroid|iPhoneSimulator.ActiveCfg = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.FDroid|iPhoneSimulator.Build.0 = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Release|Any CPU.ActiveCfg = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.AppStore|iPhone.ActiveCfg = Release|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Release|Any CPU.Build.0 = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.AppStore|iPhone.Build.0 = Release|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Release|iPhone.ActiveCfg = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Release|iPhone.Build.0 = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU {4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.FDroid|Any CPU.ActiveCfg = Debug|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.FDroid|Any CPU.Build.0 = Debug|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Debug|Any CPU.Build.0 = Debug|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Release|Any CPU.ActiveCfg = Release|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Release|Any CPU.Build.0 = Release|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.AppStore|Any CPU.Build.0 = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.AppStore|iPhone.ActiveCfg = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.AppStore|iPhone.Build.0 = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Debug|iPhone.ActiveCfg = Debug|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Debug|iPhone.Build.0 = Debug|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Release|iPhone.ActiveCfg = Release|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Release|iPhone.Build.0 = Release|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Debug|iPhone.Build.0 = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.AppStore|iPhone.ActiveCfg = Release|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.AppStore|iPhone.Build.0 = Release|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.FDroid|Any CPU.ActiveCfg = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.FDroid|Any CPU.Build.0 = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.FDroid|iPhone.ActiveCfg = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.FDroid|iPhone.Build.0 = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.FDroid|iPhoneSimulator.ActiveCfg = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.FDroid|Any CPU.ActiveCfg = Debug|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.FDroid|iPhoneSimulator.Build.0 = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.FDroid|Any CPU.Build.0 = Debug|Any CPU {8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Release|Any CPU.Build.0 = Release|Any CPU
{8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Release|iPhone.ActiveCfg = Release|Any CPU
{8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Release|iPhone.Build.0 = Release|Any CPU
{8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|Any CPU.ActiveCfg = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|Any CPU.Build.0 = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|iPhone.ActiveCfg = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|iPhone.Build.0 = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.AppStore|Any CPU.ActiveCfg = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.AppStore|Any CPU.Build.0 = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.AppStore|iPhone.ActiveCfg = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.AppStore|iPhone.Build.0 = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.AppStore|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.AppStore|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|iPhone.ActiveCfg = Debug|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|iPhone.Build.0 = Debug|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.FDroid|Any CPU.ActiveCfg = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.FDroid|Any CPU.Build.0 = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.FDroid|iPhone.ActiveCfg = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.FDroid|iPhone.Build.0 = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.FDroid|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.FDroid|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|Any CPU.ActiveCfg = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|Any CPU.Build.0 = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|iPhone.ActiveCfg = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|iPhone.Build.0 = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|Any CPU.Build.0 = Ad-Hoc|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|Any CPU.ActiveCfg = AppStore|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|Any CPU.Build.0 = AppStore|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|iPhone.Build.0 = AppStore|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|Any CPU.ActiveCfg = Debug|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|iPhone.ActiveCfg = Debug|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|iPhone.Build.0 = Debug|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|iPhone.Deploy.0 = Debug|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|Any CPU.ActiveCfg = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|Any CPU.Build.0 = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|iPhone.ActiveCfg = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|iPhone.Build.0 = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|Any CPU.ActiveCfg = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|iPhone.ActiveCfg = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|iPhone.Build.0 = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3B3A9B6C-D325-4BB3-97D3-8070630C5D3B}
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
Policies = $0
$0.DotNetNamingPolicy = $1
$1.DirectoryNamespaceAssociation = PrefixedHierarchical
EndGlobalSection
GlobalSection(NestedProjects) = preSolution GlobalSection(NestedProjects) = preSolution
{971FDF07-E288-4239-B47A-E9E7E912193B} = {B972BBFA-917F-4A10-B07E-B89CFEC6BBDC} {304400AF-F0ED-40FA-B102-EA3C3EC43E4F} = {D10CA4A9-F866-40E1-B658-F69051236C71}
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C} = {B972BBFA-917F-4A10-B07E-B89CFEC6BBDC} {EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C} = {D10CA4A9-F866-40E1-B658-F69051236C71}
{83449CC4-1F76-4CFE-92B1-D2E13A62506F} = {B972BBFA-917F-4A10-B07E-B89CFEC6BBDC} {4B8A8C41-9820-4341-974C-41E65B7F4366} = {D10CA4A9-F866-40E1-B658-F69051236C71}
{E71F3053-056C-4381-9638-048ED73BDFF6} = {B972BBFA-917F-4A10-B07E-B89CFEC6BBDC} {9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3} = {8904C536-C67D-420F-9971-51B26574C3AA}
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545} = {B972BBFA-917F-4A10-B07E-B89CFEC6BBDC} {2E399654-26A2-46F6-B9CA-1B496A3F370A} = {92470CBD-9047-4C3C-8EA3-D972D6622D84}
{F8C3F648-EA5A-4719-8005-85D1690B1655} = {B972BBFA-917F-4A10-B07E-B89CFEC6BBDC} {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D} = {2E399654-26A2-46F6-B9CA-1B496A3F370A}
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6} = {BB702EBD-3B79-4ECA-A2A6-1237B07F0AF0} {E71F3053-056C-4381-9638-048ED73BDFF6} = {D10CA4A9-F866-40E1-B658-F69051236C71}
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44} = {BB702EBD-3B79-4ECA-A2A6-1237B07F0AF0} {599E0201-420A-4C3E-A7BA-5349F72E0B15} = {D10CA4A9-F866-40E1-B658-F69051236C71}
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545} = {D10CA4A9-F866-40E1-B658-F69051236C71}
{4085B0A5-12A9-4993-B8B8-4ACE72E62E39} = {8904C536-C67D-420F-9971-51B26574C3AA}
{8AE548D9-A567-4E97-995E-93EC7DB0FDE0} = {8904C536-C67D-420F-9971-51B26574C3AA}
{F8C3F648-EA5A-4719-8005-85D1690B1655} = {D10CA4A9-F866-40E1-B658-F69051236C71}
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A} = {D10CA4A9-F866-40E1-B658-F69051236C71}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7D436EA3-8B7E-45D2-8D14-0730BD2E0410}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@@ -67,7 +67,7 @@ Task("UpdateAndroidManifest")
.Does(()=> .Does(()=>
{ {
var buildVariant = GetVariant(); var buildVariant = GetVariant();
var manifestPath = Path.Combine(_slnPath, "src", "App", "Platforms", "Android", "AndroidManifest.xml"); var manifestPath = Path.Combine(_slnPath, "src", "Android", "Properties", "AndroidManifest.xml");
// Cake.AndroidAppManifest doesn't currently enable us to access nested items so, quick (not ideal) fix: // Cake.AndroidAppManifest doesn't currently enable us to access nested items so, quick (not ideal) fix:
var manifestText = FileReadText(manifestPath); var manifestText = FileReadText(manifestPath);
@@ -119,26 +119,26 @@ Task("UpdateAndroidCodeFiles")
//We're not using _androidPackageName here because the codefile is currently slightly different string than the one in AndroidManifest.xml //We're not using _androidPackageName here because the codefile is currently slightly different string than the one in AndroidManifest.xml
var keyName = "com.8bit.bitwarden"; var keyName = "com.8bit.bitwarden";
var fixedPackageName = buildVariant.AndroidPackageName.Replace("x8bit", "8bit"); var fixedPackageName = buildVariant.AndroidPackageName.Replace("x8bit", "8bit");
var filePath = Path.Combine(_slnPath, "src", "App", "Platforms", "Android", "Services", "BiometricService.cs"); var filePath = Path.Combine(_slnPath, "src", "Android", "Services", "BiometricService.cs");
ReplaceInFile(filePath, keyName, fixedPackageName); ReplaceInFile(filePath, keyName, fixedPackageName);
var packageFileList = new string[] { var packageFileList = new string[] {
Path.Combine(_slnPath, "src", "App", "Platforms", "Android", "MainActivity.cs"), Path.Combine(_slnPath, "src", "Android", "MainActivity.cs"),
Path.Combine(_slnPath, "src", "App", "Platforms", "Android", "MainApplication.cs"), Path.Combine(_slnPath, "src", "Android", "MainApplication.cs"),
Path.Combine(_slnPath, "src", "App", "Platforms", "Android", "Constants.cs"), Path.Combine(_slnPath, "src", "Android", "Constants.cs"),
Path.Combine(_slnPath, "src", "App", "Platforms", "Android", "Accessibility", "AccessibilityService.cs"), Path.Combine(_slnPath, "src", "Android", "Accessibility", "AccessibilityService.cs"),
Path.Combine(_slnPath, "src", "App", "Platforms", "Android", "Autofill", "AutofillHelpers.cs"), Path.Combine(_slnPath, "src", "Android", "Autofill", "AutofillHelpers.cs"),
Path.Combine(_slnPath, "src", "App", "Platforms", "Android", "Autofill", "AutofillService.cs"), Path.Combine(_slnPath, "src", "Android", "Autofill", "AutofillService.cs"),
Path.Combine(_slnPath, "src", "App", "Platforms", "Android", "Receivers", "ClearClipboardAlarmReceiver.cs"), Path.Combine(_slnPath, "src", "Android", "Receivers", "ClearClipboardAlarmReceiver.cs"),
Path.Combine(_slnPath, "src", "App", "Platforms", "Android", "Receivers", "EventUploadReceiver.cs"), Path.Combine(_slnPath, "src", "Android", "Receivers", "EventUploadReceiver.cs"),
Path.Combine(_slnPath, "src", "App", "Platforms", "Android", "Receivers", "PackageReplacedReceiver.cs"), Path.Combine(_slnPath, "src", "Android", "Receivers", "PackageReplacedReceiver.cs"),
Path.Combine(_slnPath, "src", "App", "Platforms", "Android", "Receivers", "RestrictionsChangedReceiver.cs"), Path.Combine(_slnPath, "src", "Android", "Receivers", "RestrictionsChangedReceiver.cs"),
Path.Combine(_slnPath, "src", "App", "Platforms", "Android", "Services", "DeviceActionService.cs"), Path.Combine(_slnPath, "src", "Android", "Services", "DeviceActionService.cs"),
Path.Combine(_slnPath, "src", "App", "Platforms", "Android", "Services", "FileService.cs"), Path.Combine(_slnPath, "src", "Android", "Services", "FileService.cs"),
Path.Combine(_slnPath, "src", "App", "Platforms", "Android", "Tiles", "AutofillTileService.cs"), Path.Combine(_slnPath, "src", "Android", "Tiles", "AutofillTileService.cs"),
Path.Combine(_slnPath, "src", "App", "Platforms", "Android", "Tiles", "GeneratorTileService.cs"), Path.Combine(_slnPath, "src", "Android", "Tiles", "GeneratorTileService.cs"),
Path.Combine(_slnPath, "src", "App", "Platforms", "Android", "Tiles", "MyVaultTileService.cs"), Path.Combine(_slnPath, "src", "Android", "Tiles", "MyVaultTileService.cs"),
Path.Combine(_slnPath, "src", "App", "Platforms", "Android", "google-services.json"), Path.Combine(_slnPath, "src", "Android", "google-services.json"),
Path.Combine(_slnPath, "store", "google", "Publisher", "Program.cs"), Path.Combine(_slnPath, "store", "google", "Publisher", "Program.cs"),
}; };
@@ -148,7 +148,7 @@ Task("UpdateAndroidCodeFiles")
} }
var labelFileList = new string[] { var labelFileList = new string[] {
Path.Combine(_slnPath, "src", "App", "Platforms", "Android", "Autofill", "AutofillService.cs"), Path.Combine(_slnPath, "src", "Android", "Autofill", "AutofillService.cs"),
}; };
foreach(string path in labelFileList) foreach(string path in labelFileList)
@@ -315,7 +315,7 @@ private void UpdateAppleIcons(string target, string appiconsetTarget)
Task("UpdateiOSIcons") Task("UpdateiOSIcons")
.Does(()=>{ .Does(()=>{
UpdateAppleIcons("ios", Path.Combine(_slnPath, "src", "App", "Platforms", "iOS", "Resources", "Assets.xcassets", "AppIcons.appiconset")); UpdateAppleIcons("ios", Path.Combine(_slnPath, "src", "iOS", "Resources", "Assets.xcassets", "AppIcons.appiconset"));
UpdateAppleIcons("watch", Path.Combine(_slnPath, "src", "watchOS", "bitwarden", "bitwarden WatchKit App", "Assets.xcassets", "AppIcon.appiconset")); UpdateAppleIcons("watch", Path.Combine(_slnPath, "src", "watchOS", "bitwarden", "bitwarden WatchKit App", "Assets.xcassets", "AppIcon.appiconset"));
// TODO: Update complication icons when they start working // TODO: Update complication icons when they start working
}); });
@@ -324,8 +324,8 @@ Task("UpdateiOSPlist")
.IsDependentOn("GetGitInfo") .IsDependentOn("GetGitInfo")
.Does(()=> { .Does(()=> {
var buildVariant = GetVariant(); var buildVariant = GetVariant();
var infoPath = Path.Combine(_slnPath, "src", "App", "Platforms", "iOS", "Info.plist"); var infoPath = Path.Combine(_slnPath, "src", "iOS", "Info.plist");
var entitlementsPath = Path.Combine(_slnPath, "src", "App", "Platforms", "iOS", "Entitlements.plist"); var entitlementsPath = Path.Combine(_slnPath, "src", "iOS", "Entitlements.plist");
UpdateiOSInfoPlist(infoPath, buildVariant, _gitVersion, iOSProjectType.MainApp); UpdateiOSInfoPlist(infoPath, buildVariant, _gitVersion, iOSProjectType.MainApp);
UpdateiOSEntitlementsPlist(entitlementsPath, buildVariant); UpdateiOSEntitlementsPlist(entitlementsPath, buildVariant);
}); });

View File

@@ -2,9 +2,9 @@ project_id_env: _CROWDIN_PROJECT_ID
api_token_env: CROWDIN_API_TOKEN api_token_env: CROWDIN_API_TOKEN
preserve_hierarchy: true preserve_hierarchy: true
files: files:
- source: /src/Core/Resources/Localization/AppResources.resx - source: /src/App/Resources/AppResources.resx
dest: /src/Core/Resources/Localization/%original_file_name% dest: /src/App/Resources/%original_file_name%
translation: /src/Core/Resources/Localization/AppResources.%two_letters_code%.resx translation: /src/App/Resources/AppResources.%two_letters_code%.resx
update_option: update_as_unapproved update_option: update_as_unapproved
languages_mapping: languages_mapping:
two_letters_code: two_letters_code:
@@ -38,15 +38,3 @@ files:
pt-PT: pt-PT pt-PT: pt-PT
en-GB: en-GB en-GB: en-GB
en-IN: en-IN en-IN: en-IN
- source: "/src/watchOS/bitwarden/bitwarden WatchKit Extension/Localization/en.lproj/Localizable.strings"
dest: "/src/watchOS/bitwarden/bitwarden WatchKit Extension/Localization/en.lproj/%original_file_name%"
translation: "/src/watchOS/bitwarden/bitwarden WatchKit Extension/Localization//%two_letters_code%.lproj/%original_file_name%"
update_option: update_as_unapproved
languages_mapping:
two_letters_code:
zh-CN: zh-Hans
zh-TW: zh-Hant
pt-BR: pt-BR
pt-PT: pt-PT
en-GB: en-GB
en-IN: en-IN

BIN
lib/ios/libbitwarden_c.a Normal file

Binary file not shown.

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="MAUI Nightly builds" value="https://pkgs.dev.azure.com/xamarin/public/_packaging/maui-nightly/nuget/v3/index.json" />
</packageSources>
</configuration>

2
package-lock.json generated
View File

@@ -8,7 +8,7 @@
"name": "bitwarden-mobile", "name": "bitwarden-mobile",
"version": "0.0.0", "version": "0.0.0",
"devDependencies": { "devDependencies": {
"gh-pages": "3.2.3" "gh-pages": "^3.2.3"
} }
}, },
"node_modules/array-union": { "node_modules/array-union": {

View File

@@ -6,6 +6,6 @@
"clean:l10n": "git push origin --delete l10n_master" "clean:l10n": "git push origin --delete l10n_master"
}, },
"devDependencies": { "devDependencies": {
"gh-pages": "3.2.3" "gh-pages": "^3.2.3"
} }
} }

View File

@@ -6,7 +6,7 @@ using Android.Views;
using System; using System;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Bit.App.Droid.Utilities; using Bit.Droid.Utilities;
namespace Bit.Droid.Accessibility namespace Bit.Droid.Accessibility
{ {

View File

@@ -10,13 +10,8 @@ using Android.Runtime;
using Android.Views; using Android.Views;
using Android.Views.Accessibility; using Android.Views.Accessibility;
using Android.Widget; using Android.Widget;
using Bit.Core.Resources.Localization; using Bit.App.Resources;
using Bit.Core; using Bit.Core;
using Application = Android.App.Application;
using View = Android.Views.View;
using Resource = Bit.Core.Resource;
using Point = Android.Graphics.Point;
using Rect = Android.Graphics.Rect;
namespace Bit.Droid.Accessibility namespace Bit.Droid.Accessibility
{ {
@@ -112,7 +107,6 @@ namespace Bit.Droid.Accessibility
new Browser("org.bromite.chromium", "url_bar"), new Browser("org.bromite.chromium", "url_bar"),
new Browser("org.chromium.chrome", "url_bar"), new Browser("org.chromium.chrome", "url_bar"),
new Browser("org.codeaurora.swe.browser", "url_bar"), new Browser("org.codeaurora.swe.browser", "url_bar"),
new Browser("org.cromite.cromite", "url_bar"),
new Browser("org.gnu.icecat", "url_bar_title,mozac_browser_toolbar_url_view"), // 2nd = Anticipation new Browser("org.gnu.icecat", "url_bar_title,mozac_browser_toolbar_url_view"), // 2nd = Anticipation
new Browser("org.mozilla.fenix", "mozac_browser_toolbar_url_view"), new Browser("org.mozilla.fenix", "mozac_browser_toolbar_url_view"),
new Browser("org.mozilla.fenix.nightly", "mozac_browser_toolbar_url_view"), // [DEPRECATED ENTRY] new Browser("org.mozilla.fenix.nightly", "mozac_browser_toolbar_url_view"), // [DEPRECATED ENTRY]
@@ -710,7 +704,7 @@ namespace Bit.Droid.Accessibility
public static LinearLayout GetOverlayView(Context context) public static LinearLayout GetOverlayView(Context context)
{ {
var inflater = (LayoutInflater)context.GetSystemService(Context.LayoutInflaterService); var inflater = (LayoutInflater)context.GetSystemService(Context.LayoutInflaterService);
var view = (LinearLayout)inflater.Inflate(Bit.Core.Resource.Layout.autofill_listitem, null); var view = (LinearLayout)inflater.Inflate(Resource.Layout.autofill_listitem, null);
var text1 = (TextView)view.FindViewById(Resource.Id.text1); var text1 = (TextView)view.FindViewById(Resource.Id.text1);
var text2 = (TextView)view.FindViewById(Resource.Id.text2); var text2 = (TextView)view.FindViewById(Resource.Id.text2);
var icon = (ImageView)view.FindViewById(Resource.Id.icon); var icon = (ImageView)view.FindViewById(Resource.Id.icon);

View File

@@ -9,10 +9,9 @@ using Android.Runtime;
using Android.Views; using Android.Views;
using Android.Views.Accessibility; using Android.Views.Accessibility;
using Android.Widget; using Android.Widget;
using Bit.Core.Resources.Localization; using Bit.App.Resources;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using View = Android.Views.View;
namespace Bit.Droid.Accessibility namespace Bit.Droid.Accessibility
{ {

307
src/Android/Android.csproj Normal file
View File

@@ -0,0 +1,307 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{304400AF-F0ED-40FA-B102-EA3C3EC43E4F}</ProjectGuid>
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<TemplateGuid>{c9e5eea5-ca05-42a1-839b-61506e0a37df}</TemplateGuid>
<OutputType>Library</OutputType>
<RootNamespace>Bit.Droid</RootNamespace>
<AssemblyName>BitwardenAndroid</AssemblyName>
<AndroidApplication>True</AndroidApplication>
<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
<AndroidResgenClass>Resource</AndroidResgenClass>
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
<TargetFrameworkVersion>v13.0</TargetFrameworkVersion>
<AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>portable</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>3</WarningLevel>
<AndroidSupportedAbis />
<JavaMaximumHeapSize>1G</JavaMaximumHeapSize>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugSymbols>false</DebugSymbols>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidManagedSymbols>true</AndroidManagedSymbols>
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
<AndroidSupportedAbis>armeabi-v7a;x86;x86_64;arm64-v8a</AndroidSupportedAbis>
<JavaMaximumHeapSize>1G</JavaMaximumHeapSize>
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
<AndroidEnableProfiledAot>true</AndroidEnableProfiledAot>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'FDroid|AnyCPU'">
<DebugSymbols>false</DebugSymbols>
<OutputPath>bin\FDroid\</OutputPath>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<DefineConstants>FDROID</DefineConstants>
<AndroidSupportedAbis>armeabi-v7a;x86;x86_64;arm64-v8a</AndroidSupportedAbis>
<JavaMaximumHeapSize>1G</JavaMaximumHeapSize>
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
<AndroidEnableProfiledAot>true</AndroidEnableProfiledAot>
</PropertyGroup>
<ItemGroup>
<Reference Include="Mono.Android" />
<Reference Include="Mono.Android.Export" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Xml" />
<Reference Include="System.Net.Http" Condition="'$(Configuration)'=='FDroid'" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Plugin.CurrentActivity">
<Version>2.1.0.4</Version>
</PackageReference>
<PackageReference Include="Portable.BouncyCastle">
<Version>1.9.0</Version>
</PackageReference>
<PackageReference Include="Xamarin.AndroidX.AppCompat" Version="1.5.1.1" />
<PackageReference Include="Xamarin.AndroidX.AutoFill" Version="1.1.0.14" />
<PackageReference Include="Xamarin.AndroidX.CardView" Version="1.0.0.17" />
<PackageReference Include="Xamarin.AndroidX.Core" Version="1.9.0.1" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0.15" />
<PackageReference Include="Xamarin.AndroidX.MediaRouter" Version="1.3.1.1" />
<PackageReference Include="Xamarin.Essentials">
<Version>1.7.3</Version>
</PackageReference>
<PackageReference Include="Xamarin.Firebase.Messaging">
<Version>123.0.8</Version>
</PackageReference>
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.6.1.1" />
<PackageReference Include="Xamarin.Google.Dagger" Version="2.41.0.2" />
<PackageReference Include="Xamarin.GooglePlayServices.SafetyNet">
<Version>118.0.1.2</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Compile Include="Accessibility\AccessibilityActivity.cs" />
<Compile Include="Accessibility\AccessibilityHelpers.cs" />
<Compile Include="Accessibility\Credentials.cs" />
<Compile Include="Accessibility\AccessibilityService.cs" />
<Compile Include="Accessibility\Browser.cs" />
<Compile Include="Accessibility\NodeList.cs" />
<Compile Include="Accessibility\KnownUsernameField.cs" />
<Compile Include="Autofill\AutofillConstants.cs" />
<Compile Include="Autofill\AutofillHelpers.cs" />
<Compile Include="Autofill\AutofillService.cs" />
<Compile Include="Autofill\AutofillExternalSelectionActivity.cs" />
<Compile Include="Autofill\Field.cs" />
<Compile Include="Autofill\FieldCollection.cs" />
<Compile Include="Autofill\FilledItem.cs" />
<Compile Include="Autofill\Parser.cs" />
<Compile Include="Autofill\SavedItem.cs" />
<Compile Include="Effects\FabShadowEffect.cs" />
<Compile Include="Effects\FixedSizeEffect.cs" />
<Compile Include="Effects\TabBarEffect.cs" />
<Compile Include="Push\FirebaseMessagingService.cs" />
<Compile Include="Receivers\ClearClipboardAlarmReceiver.cs" />
<Compile Include="Receivers\RestrictionsChangedReceiver.cs" />
<Compile Include="Receivers\EventUploadReceiver.cs" />
<Compile Include="Receivers\PackageReplacedReceiver.cs" />
<Compile Include="Renderers\ExtendedGridRenderer.cs" />
<Compile Include="Renderers\ExtendedDatePickerRenderer.cs" />
<Compile Include="Renderers\CustomTabbedRenderer.cs" />
<Compile Include="Renderers\ExtendedStackLayoutRenderer.cs" />
<Compile Include="Renderers\ExtendedStepperRenderer.cs" />
<Compile Include="Renderers\CustomSwitchRenderer.cs" />
<Compile Include="Renderers\ExtendedTimePickerRenderer.cs" />
<Compile Include="Renderers\ExtendedSliderRenderer.cs" />
<Compile Include="Renderers\CustomEditorRenderer.cs" />
<Compile Include="Renderers\CustomPickerRenderer.cs" />
<Compile Include="Renderers\CustomEntryRenderer.cs" />
<Compile Include="Renderers\CustomSearchBarRenderer.cs" />
<Compile Include="Renderers\HybridWebViewRenderer.cs" />
<Compile Include="Services\AndroidPushNotificationService.cs" />
<Compile Include="Services\AndroidLogService.cs" />
<Compile Include="MainApplication.cs" />
<Compile Include="MainActivity.cs" />
<Compile Include="Resources\Resource.designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Services\BiometricService.cs" />
<Compile Include="Services\CryptoPrimitiveService.cs" />
<Compile Include="Services\DeviceActionService.cs" />
<Compile Include="Services\LocalizeService.cs" />
<Compile Include="Tiles\AutofillTileService.cs" />
<Compile Include="Tiles\GeneratorTileService.cs" />
<Compile Include="Tiles\MyVaultTileService.cs" />
<Compile Include="Utilities\AndroidHelpers.cs" />
<Compile Include="Utilities\ThemeHelpers.cs" />
<Compile Include="WebAuthCallbackActivity.cs" />
<Compile Include="Renderers\SelectableLabelRenderer.cs" />
<Compile Include="Services\ClipboardService.cs" />
<Compile Include="Utilities\IntentExtensions.cs" />
<Compile Include="Renderers\CustomPageRenderer.cs" />
<Compile Include="Effects\NoEmojiKeyboardEffect.cs" />
<Compile Include="Receivers\NotificationDismissReceiver.cs" />
<Compile Include="Services\FileService.cs" />
<Compile Include="Services\AutofillHandler.cs" />
<Compile Include="Constants.cs" />
<Compile Include="Effects\RemoveFontPaddingEffect.cs" />
<Compile Include="Services\WatchDeviceService.cs" />
</ItemGroup>
<ItemGroup>
<AndroidAsset Include="Assets\bwi-font.ttf" />
<AndroidAsset Include="Assets\RobotoMono_Regular.ttf" />
<AndroidAsset Include="Assets\MaterialIcons_Regular.ttf" />
<None Include="8bit.keystore.enc" />
<GoogleServicesJson Include="google-services.json" />
<GoogleServicesJson Include="google-services.json.enc" />
<None Include="fdroid-keystore.jks.enc" />
<AndroidNativeLibrary Include="lib\arm64-v8a\libargon2.so" />
<AndroidNativeLibrary Include="lib\armeabi-v7a\libargon2.so" />
<AndroidNativeLibrary Include="lib\x86\libargon2.so" />
<AndroidNativeLibrary Include="lib\x86_64\libargon2.so" />
<None Include="Properties\AndroidManifest.xml" />
<None Include="upload-keystore.jks.enc" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\logo_legacy.png" />
<AndroidResource Include="Resources\drawable-hdpi\logo_white_legacy.png" />
<AndroidResource Include="Resources\drawable-xhdpi\logo_legacy.png" />
<AndroidResource Include="Resources\drawable-xhdpi\logo_white_legacy.png" />
<AndroidResource Include="Resources\drawable-xxhdpi\logo_legacy.png" />
<AndroidResource Include="Resources\drawable-xxhdpi\logo_white_legacy.png" />
<AndroidResource Include="Resources\drawable\card.xml" />
<AndroidResource Include="Resources\drawable\cog_environment.xml" />
<AndroidResource Include="Resources\drawable\cog_settings.xml" />
<AndroidResource Include="Resources\drawable\icon.xml" />
<AndroidResource Include="Resources\drawable\ic_launcher_foreground.xml" />
<AndroidResource Include="Resources\drawable\ic_launcher_monochrome.xml" />
<AndroidResource Include="Resources\drawable\ic_warning.xml" />
<AndroidResource Include="Resources\drawable\id.xml" />
<AndroidResource Include="Resources\drawable\info.xml" />
<AndroidResource Include="Resources\drawable\list_item_bg.xml" />
<AndroidResource Include="Resources\drawable\lock.xml" />
<AndroidResource Include="Resources\drawable\login.xml" />
<AndroidResource Include="Resources\drawable\logo.xml" />
<AndroidResource Include="Resources\drawable\logo_white.xml" />
<AndroidResource Include="Resources\drawable\send.xml" />
<AndroidResource Include="Resources\drawable\pencil.xml" />
<AndroidResource Include="Resources\drawable\plus.xml" />
<AndroidResource Include="Resources\drawable\generate.xml" />
<AndroidResource Include="Resources\drawable\search.xml" />
<AndroidResource Include="Resources\drawable\shield.xml" />
<AndroidResource Include="Resources\drawable-v23\splash_screen.xml" />
<AndroidResource Include="Resources\drawable-v23\splash_screen_dark.xml" />
<AndroidResource Include="Resources\drawable\switch_thumb.xml" />
<AndroidResource Include="Resources\layout\progress_dialog_layout.xml" />
<AndroidResource Include="Resources\layout\Tabbar.axml" />
<AndroidResource Include="Resources\layout\Toolbar.axml" />
<AndroidResource Include="Resources\mipmap-anydpi-v26\ic_launcher.xml" />
<AndroidResource Include="Resources\mipmap-anydpi-v26\ic_launcher_round.xml" />
<AndroidResource Include="Resources\mipmap-hdpi\ic_launcher.png" />
<AndroidResource Include="Resources\mipmap-hdpi\ic_launcher_round.png" />
<AndroidResource Include="Resources\mipmap-mdpi\ic_launcher.png" />
<AndroidResource Include="Resources\mipmap-mdpi\ic_launcher_round.png" />
<AndroidResource Include="Resources\mipmap-xhdpi\ic_launcher.png" />
<AndroidResource Include="Resources\mipmap-xhdpi\ic_launcher_round.png" />
<AndroidResource Include="Resources\mipmap-xxhdpi\ic_launcher.png" />
<AndroidResource Include="Resources\mipmap-xxhdpi\ic_launcher_round.png" />
<AndroidResource Include="Resources\mipmap-xxxhdpi\ic_launcher.png" />
<AndroidResource Include="Resources\mipmap-xxxhdpi\ic_launcher_round.png" />
<AndroidResource Include="Resources\values-night\styles.xml" />
<AndroidResource Include="Resources\values\styles.xml" />
<AndroidResource Include="Resources\values\colors.xml" />
<AndroidResource Include="Resources\values\manifest.xml" />
<AndroidResource Include="Resources\values-v30\manifest.xml" />
<AndroidResource Include="Resources\drawable-v26\splash_screen_round.xml" />
<AndroidResource Include="Resources\drawable\logo_rounded.xml" />
<AndroidResource Include="Resources\drawable-night-v26\splash_screen_round.xml" />
<AndroidResource Include="Resources\drawable\ic_notification.xml">
<SubType></SubType>
<Generator></Generator>
</AndroidResource>
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\splash_screen.xml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\App\App.csproj">
<Project>{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}</Project>
<Name>App</Name>
</ProjectReference>
<ProjectReference Include="..\Core\Core.csproj">
<Project>{4b8a8c41-9820-4341-974c-41e65b7f4366}</Project>
<Name>Core</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\xml\accessibilityservice.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\xml\autofillservice.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\xml\filepaths.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\xml\network_security_config.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\values\strings.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\values\ic_launcher_background.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\layout\autofill_listitem.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\yubikey.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\yubikey.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\yubikey.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\slider_thumb.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\splash_screen_dark.xml">
<Generator>MSBuild:UpdateGeneratedFiles</Generator>
<SubType>Designer</SubType>
</AndroidResource>
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\values\dimens.xml">
<Generator>MSBuild:UpdateGeneratedFiles</Generator>
<SubType>Designer</SubType>
</AndroidResource>
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\xml\app_restrictions.xml">
<Generator>MSBuild:UpdateGeneratedFiles</Generator>
<SubType>Designer</SubType>
</AndroidResource>
</ItemGroup>
<ItemGroup>
<Folder Include="Resources\values-v30\" />
<Folder Include="Resources\drawable-v26\" />
<Folder Include="Resources\drawable-night-v26\" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
</Project>

View File

@@ -4,14 +4,14 @@ using Android.Content.PM;
using Android.OS; using Android.OS;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Bit.App.Droid.Utilities; using Bit.Droid.Utilities;
namespace Bit.Droid.Autofill namespace Bit.Droid.Autofill
{ {
[Activity( [Activity(
NoHistory = true, NoHistory = true,
LaunchMode = LaunchMode.SingleTop)] LaunchMode = LaunchMode.SingleTop)]
public class AutofillExternalSelectionActivity : MauiAppCompatActivity public class AutofillExternalSelectionActivity : Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{ {
protected override void OnCreate(Bundle bundle) protected override void OnCreate(Bundle bundle)
{ {

View File

@@ -12,17 +12,14 @@ using Android.Graphics.Drawables;
using Android.OS; using Android.OS;
using Android.Runtime; using Android.Runtime;
using Android.Widget.Inline; using Android.Widget.Inline;
using Bit.Core.Resources.Localization; using Bit.App.Resources;
using Bit.Core.Enums; using Bit.Core.Enums;
using Android.Views.Autofill; using Android.Views.Autofill;
using AndroidX.AutoFill.Inline; using AndroidX.AutoFill.Inline;
using AndroidX.AutoFill.Inline.V1; using AndroidX.AutoFill.Inline.V1;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using SaveFlags = Android.Service.Autofill.SaveFlags; using SaveFlags = Android.Service.Autofill.SaveFlags;
using Bit.App.Droid.Utilities; using Bit.Droid.Utilities;
using Bit.Core.Services;
using Resource = Bit.Core.Resource;
using BlendMode = Android.Graphics.BlendMode;
namespace Bit.Droid.Autofill namespace Bit.Droid.Autofill
{ {
@@ -130,7 +127,6 @@ namespace Bit.Droid.Autofill
"org.bromite.chromium", "org.bromite.chromium",
"org.chromium.chrome", "org.chromium.chrome",
"org.codeaurora.swe.browser", "org.codeaurora.swe.browser",
"org.cromite.cromite",
"org.gnu.icecat", "org.gnu.icecat",
"org.mozilla.fenix", "org.mozilla.fenix",
"org.mozilla.fenix.nightly", "org.mozilla.fenix.nightly",
@@ -156,9 +152,8 @@ namespace Bit.Droid.Autofill
"androidapp://com.oneplus.applocker", "androidapp://com.oneplus.applocker",
}; };
public static async Task<List<FilledItem>> GetFillItemsAsync(Parser parser, ICipherService cipherService, IUserVerificationService userVerificationService) public static async Task<List<FilledItem>> GetFillItemsAsync(Parser parser, ICipherService cipherService)
{ {
var userHasMasterPassword = await userVerificationService.HasMasterPasswordAsync();
if (parser.FieldCollection.FillableForLogin) if (parser.FieldCollection.FillableForLogin)
{ {
var ciphers = await cipherService.GetAllDecryptedByUrlAsync(parser.Uri); var ciphers = await cipherService.GetAllDecryptedByUrlAsync(parser.Uri);
@@ -166,14 +161,14 @@ namespace Bit.Droid.Autofill
{ {
var allCiphers = ciphers.Item1.ToList(); var allCiphers = ciphers.Item1.ToList();
allCiphers.AddRange(ciphers.Item2.ToList()); allCiphers.AddRange(ciphers.Item2.ToList());
var nonPromptCiphers = allCiphers.Where(cipher => !userHasMasterPassword || cipher.Reprompt == CipherRepromptType.None); var nonPromptCiphers = allCiphers.Where(cipher => cipher.Reprompt == CipherRepromptType.None);
return nonPromptCiphers.Select(c => new FilledItem(c)).ToList(); return nonPromptCiphers.Select(c => new FilledItem(c)).ToList();
} }
} }
else if (parser.FieldCollection.FillableForCard) else if (parser.FieldCollection.FillableForCard)
{ {
var ciphers = await cipherService.GetAllDecryptedAsync(); var ciphers = await cipherService.GetAllDecryptedAsync();
return ciphers.Where(c => c.Type == CipherType.Card && (!userHasMasterPassword || c.Reprompt == CipherRepromptType.None)).Select(c => new FilledItem(c)).ToList(); return ciphers.Where(c => c.Type == CipherType.Card && c.Reprompt == CipherRepromptType.None).Select(c => new FilledItem(c)).ToList();
} }
return new List<FilledItem>(); return new List<FilledItem>();
} }
@@ -347,7 +342,7 @@ namespace Bit.Droid.Autofill
// InlinePresentation requires nonNull pending intent (even though we only utilize one for the // InlinePresentation requires nonNull pending intent (even though we only utilize one for the
// "my vault" presentation) so we're including an empty one here // "my vault" presentation) so we're including an empty one here
pendingIntent = PendingIntent.GetService(context, 0, new Intent(), pendingIntent = PendingIntent.GetService(context, 0, new Intent(),
AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.OneShot | PendingIntentFlags.UpdateCurrent, false)); AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.OneShot | PendingIntentFlags.UpdateCurrent, true));
} }
var slice = CreateInlinePresentationSlice( var slice = CreateInlinePresentationSlice(
inlinePresentationSpec, inlinePresentationSpec,

View File

@@ -11,7 +11,6 @@ using Android.Widget;
using Bit.Core; using Bit.Core;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Services;
using Bit.Core.Utilities; using Bit.Core.Utilities;
namespace Bit.Droid.Autofill namespace Bit.Droid.Autofill
@@ -27,7 +26,6 @@ namespace Bit.Droid.Autofill
private IPolicyService _policyService; private IPolicyService _policyService;
private IStateService _stateService; private IStateService _stateService;
private LazyResolve<ILogger> _logger = new LazyResolve<ILogger>("logger"); private LazyResolve<ILogger> _logger = new LazyResolve<ILogger>("logger");
private IUserVerificationService _userVerificationService;
public async override void OnFillRequest(FillRequest request, CancellationSignal cancellationSignal, public async override void OnFillRequest(FillRequest request, CancellationSignal cancellationSignal,
FillCallback callback) FillCallback callback)
@@ -66,9 +64,11 @@ namespace Bit.Droid.Autofill
var locked = await _vaultTimeoutService.IsLockedAsync(); var locked = await _vaultTimeoutService.IsLockedAsync();
if (!locked) if (!locked)
{ {
_cipherService ??= ServiceContainer.Resolve<ICipherService>(); if (_cipherService == null)
_userVerificationService ??= ServiceContainer.Resolve<IUserVerificationService>(); {
items = await AutofillHelpers.GetFillItemsAsync(parser, _cipherService, _userVerificationService); _cipherService = ServiceContainer.Resolve<ICipherService>("cipherService");
}
items = await AutofillHelpers.GetFillItemsAsync(parser, _cipherService);
} }
// build response // build response

View File

@@ -6,7 +6,6 @@ using Android.Views.Autofill;
using static Android.App.Assist.AssistStructure; using static Android.App.Assist.AssistStructure;
using Android.Text; using Android.Text;
using static Android.Views.ViewStructure; using static Android.Views.ViewStructure;
using View = Android.Views.View;
namespace Bit.Droid.Autofill namespace Bit.Droid.Autofill
{ {

View File

@@ -4,7 +4,6 @@ using Android.Views.Autofill;
using System.Linq; using System.Linq;
using Android.Text; using Android.Text;
using Android.Views; using Android.Views;
using View = Android.Views.View;
namespace Bit.Droid.Autofill namespace Bit.Droid.Autofill
{ {
@@ -13,7 +12,7 @@ namespace Bit.Droid.Autofill
private List<Field> _passwordFields = null; private List<Field> _passwordFields = null;
private List<Field> _usernameFields = null; private List<Field> _usernameFields = null;
private HashSet<string> _ignoreSearchTerms = new HashSet<string> { "search", "find", "recipient", "edit" }; private HashSet<string> _ignoreSearchTerms = new HashSet<string> { "search", "find", "recipient", "edit" };
private HashSet<string> _usernameTerms = new HashSet<string> { "email", "phone", "username" }; private HashSet<string> _usernameTerms = new HashSet<string> { "email", "phone", "username"};
private HashSet<string> _passwordTerms = new HashSet<string> { "password", "pswd" }; private HashSet<string> _passwordTerms = new HashSet<string> { "password", "pswd" };
public List<AutofillId> AutofillIds { get; private set; } = new List<AutofillId>(); public List<AutofillId> AutofillIds { get; private set; } = new List<AutofillId>();
@@ -55,14 +54,15 @@ namespace Bit.Droid.Autofill
if (HintToFieldsMap.ContainsKey(View.AutofillHintPassword)) if (HintToFieldsMap.ContainsKey(View.AutofillHintPassword))
{ {
_passwordFields.AddRange(HintToFieldsMap[View.AutofillHintPassword]); _passwordFields.AddRange(HintToFieldsMap[View.AutofillHintPassword]);
return _passwordFields;
} }
} }
else
_passwordFields = Fields.Where(f => FieldIsPassword(f)).ToList();
if (!_passwordFields.Any())
{ {
_passwordFields = Fields.Where(f => FieldHasPasswordTerms(f)).ToList(); _passwordFields = Fields.Where(f => FieldIsPassword(f)).ToList();
if (!_passwordFields.Any())
{
_passwordFields = Fields.Where(f => FieldHasPasswordTerms(f)).ToList();
}
} }
return _passwordFields; return _passwordFields;
} }
@@ -87,25 +87,23 @@ namespace Bit.Droid.Autofill
{ {
_usernameFields.AddRange(HintToFieldsMap[View.AutofillHintUsername]); _usernameFields.AddRange(HintToFieldsMap[View.AutofillHintUsername]);
} }
if (_usernameFields.Any())
{
return _usernameFields;
}
} }
else
foreach (var passwordField in PasswordFields)
{ {
var usernameField = Fields.TakeWhile(f => f.AutofillId != passwordField.AutofillId) foreach (var passwordField in PasswordFields)
.LastOrDefault();
if (usernameField != null)
{ {
_usernameFields.Add(usernameField); var usernameField = Fields.TakeWhile(f => f.AutofillId != passwordField.AutofillId)
.LastOrDefault();
if (usernameField != null)
{
_usernameFields.Add(usernameField);
}
} }
}
if (!_usernameFields.Any()) if (!_usernameFields.Any())
{ {
_usernameFields = Fields.Where(f => FieldIsUsername(f)).ToList(); _usernameFields = Fields.Where(f => FieldIsUsername(f)).ToList();
}
} }
return _usernameFields; return _usernameFields;
} }

View File

@@ -4,7 +4,6 @@ using System.Linq;
using Bit.Core.Enums; using Bit.Core.Enums;
using Android.Views; using Android.Views;
using Bit.Core.Models.View; using Bit.Core.Models.View;
using Resource = Bit.Core.Resource;
namespace Bit.Droid.Autofill namespace Bit.Droid.Autofill
{ {

7
src/Android/Constants.cs Normal file
View File

@@ -0,0 +1,7 @@
namespace Bit.Droid
{
public static class Constants
{
public const string PACKAGE_NAME = "com.x8bit.bitwarden";
}
}

View File

@@ -0,0 +1,30 @@
using Android.Graphics.Drawables;
using Bit.Droid.Effects;
using Bit.Droid.Utilities;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportEffect(typeof(FabShadowEffect), "FabShadowEffect")]
namespace Bit.Droid.Effects
{
public class FabShadowEffect : PlatformEffect
{
protected override void OnAttached ()
{
if (Control is Android.Widget.Button button)
{
var gd = new GradientDrawable();
gd.SetColor(ThemeHelpers.FabColor);
gd.SetCornerRadius(100);
button.SetBackground(gd);
button.Elevation = 6;
button.TranslationZ = 20;
}
}
protected override void OnDetached ()
{
}
}
}

View File

@@ -0,0 +1,23 @@
using Android.Widget;
using Bit.Droid.Effects;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportEffect(typeof(FixedSizeEffect), "FixedSizeEffect")]
namespace Bit.Droid.Effects
{
public class FixedSizeEffect : PlatformEffect
{
protected override void OnAttached()
{
if (Element is Label label && Control is TextView textView)
{
textView.SetTextSize(Android.Util.ComplexUnitType.Pt, (float)label.FontSize);
}
}
protected override void OnDetached()
{
}
}
}

View File

@@ -1,20 +1,12 @@
using System; using Android.Widget;
using Microsoft.Maui.Controls; using Bit.Droid.Effects;
using Microsoft.Maui; using Xamarin.Forms;
using Microsoft.Maui.Controls.Platform; using Xamarin.Forms.Platform.Android;
#if ANDROID [assembly: ExportEffect(typeof(NoEmojiKeyboardEffect), nameof(NoEmojiKeyboardEffect))]
using Android.Widget; namespace Bit.Droid.Effects
#endif
namespace Bit.App.Effects
{ {
public class NoEmojiKeyboardEffect : RoutingEffect public class NoEmojiKeyboardEffect : PlatformEffect
{
}
#if ANDROID
public class NoEmojiKeyboardPlatformEffect : PlatformEffect
{ {
protected override void OnAttached() protected override void OnAttached()
{ {
@@ -28,5 +20,5 @@ namespace Bit.App.Effects
{ {
} }
} }
#endif
} }

View File

@@ -0,0 +1,23 @@
using Android.Widget;
using Bit.Droid.Effects;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportEffect(typeof(RemoveFontPaddingEffect), nameof(RemoveFontPaddingEffect))]
namespace Bit.Droid.Effects
{
public class RemoveFontPaddingEffect : PlatformEffect
{
protected override void OnAttached()
{
if (Control is TextView textView)
{
textView.SetIncludeFontPadding(false);
}
}
protected override void OnDetached()
{
}
}
}

View File

@@ -0,0 +1,30 @@
using Android.Views;
using Bit.Droid.Effects;
using Google.Android.Material.BottomNavigation;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ResolutionGroupName("Bitwarden")]
[assembly: ExportEffect(typeof(TabBarEffect), "TabBarEffect")]
namespace Bit.Droid.Effects
{
public class TabBarEffect : PlatformEffect
{
protected override void OnAttached()
{
if (!(Container.GetChildAt(0) is ViewGroup layout))
{
return;
}
if (!(layout.GetChildAt(1) is BottomNavigationView bottomNavigationView))
{
return;
}
bottomNavigationView.LabelVisibilityMode = LabelVisibilityMode.LabelVisibilityLabeled;
}
protected override void OnDetached()
{
}
}
}

View File

@@ -12,7 +12,7 @@ using Android.Runtime;
using Android.Views; using Android.Views;
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.App.Models; using Bit.App.Models;
using Bit.Core.Resources.Localization; using Bit.App.Resources;
using Bit.App.Utilities; using Bit.App.Utilities;
using Bit.Core; using Bit.Core;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
@@ -20,9 +20,11 @@ using Bit.Core.Enums;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Bit.Droid.Autofill; using Bit.Droid.Autofill;
using Bit.Droid.Receivers; using Bit.Droid.Receivers;
using Bit.App.Droid.Utilities; using Bit.Droid.Utilities;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Xamarin.Essentials;
using ZXing.Net.Mobile.Android;
using FileProvider = AndroidX.Core.Content.FileProvider; using FileProvider = AndroidX.Core.Content.FileProvider;
namespace Bit.Droid namespace Bit.Droid
@@ -32,7 +34,7 @@ namespace Bit.Droid
// LaunchMode defined in values/manifest.xml for Android 10- and values-v30/manifest.xml for Android 11+ // LaunchMode defined in values/manifest.xml for Android 10- and values-v30/manifest.xml for Android 11+
// See https://github.com/bitwarden/mobile/pull/1673 for details // See https://github.com/bitwarden/mobile/pull/1673 for details
[Register("com.x8bit.bitwarden.MainActivity")] [Register("com.x8bit.bitwarden.MainActivity")]
public class MainActivity : MauiAppCompatActivity public class MainActivity : Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{ {
private IDeviceActionService _deviceActionService; private IDeviceActionService _deviceActionService;
private IFileService _fileService; private IFileService _fileService;
@@ -68,17 +70,12 @@ namespace Bit.Droid
_pushNotificationListenerService = ServiceContainer.Resolve<IPushNotificationListenerService>(); _pushNotificationListenerService = ServiceContainer.Resolve<IPushNotificationListenerService>();
_logger = ServiceContainer.Resolve<ILogger>("logger"); _logger = ServiceContainer.Resolve<ILogger>("logger");
//TabLayoutResource = Resource.Layout.Tabbar; TabLayoutResource = Resource.Layout.Tabbar;
//ToolbarResource = Resource.Layout.Toolbar; ToolbarResource = Resource.Layout.Toolbar;
// this needs to be called here before base.OnCreate(...) // this needs to be called here before base.OnCreate(...)
Intent?.Validate(); Intent?.Validate();
//We need to get and set the Options before calling OnCreate as that will "trigger" CreateWindow on App.xaml.cs
_appOptions = GetOptions();
//This does not replace existing Options in App.xaml.cs if it exists already. It only updates properties in Options related with Autofill/CreateSend/etc..
((Bit.App.App)Microsoft.Maui.Controls.Application.Current).SetAndroidOptions(_appOptions);
base.OnCreate(savedInstanceState); base.OnCreate(savedInstanceState);
_deviceActionService.SetScreenCaptureAllowedAsync().FireAndForget(_ => _deviceActionService.SetScreenCaptureAllowedAsync().FireAndForget(_ =>
@@ -94,7 +91,11 @@ namespace Bit.Droid
toplayout.FilterTouchesWhenObscured = true; toplayout.FilterTouchesWhenObscured = true;
} }
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
Xamarin.Forms.Forms.Init(this, savedInstanceState);
_appOptions = GetOptions();
CreateNotificationChannel(); CreateNotificationChannel();
LoadApplication(new App.App(_appOptions));
DisableAndroidFontScale(); DisableAndroidFontScale();
_broadcasterService.Subscribe(_activityKey, (message) => _broadcasterService.Subscribe(_activityKey, (message) =>
@@ -109,15 +110,15 @@ namespace Bit.Droid
} }
else if (message.Command == "finishMainActivity") else if (message.Command == "finishMainActivity")
{ {
MainThread.BeginInvokeOnMainThread(() => Finish()); Xamarin.Forms.Device.BeginInvokeOnMainThread(() => Finish());
} }
else if (message.Command == "listenYubiKeyOTP") else if (message.Command == "listenYubiKeyOTP")
{ {
ListenYubiKey((bool)message.Data); ListenYubiKey((bool)message.Data);
} }
else if (message.Command is ThemeManager.UPDATED_THEME_MESSAGE_KEY) else if (message.Command == "updatedTheme")
{ {
MainThread.BeginInvokeOnMainThread(() => AppearanceAdjustments()); Xamarin.Forms.Device.BeginInvokeOnMainThread(() => AppearanceAdjustments());
} }
else if (message.Command == "exit") else if (message.Command == "exit")
{ {
@@ -135,7 +136,7 @@ namespace Bit.Droid
protected override void OnResume() protected override void OnResume()
{ {
base.OnResume(); base.OnResume();
//Xamarin.Essentials.Platform.OnResume(); Xamarin.Essentials.Platform.OnResume();
AppearanceAdjustments(); AppearanceAdjustments();
ThemeManager.UpdateThemeOnPagesAsync(); ThemeManager.UpdateThemeOnPagesAsync();
@@ -223,9 +224,8 @@ namespace Bit.Droid
} }
else else
{ {
Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults); Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
//Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults); PermissionsHandler.OnRequestPermissionsResult(requestCode, permissions, grantResults);
//PermissionsHandler.OnRequestPermissionsResult(requestCode, permissions, grantResults);
} }
base.OnRequestPermissionsResult(requestCode, permissions, grantResults); base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
} }
@@ -239,22 +239,18 @@ namespace Bit.Droid
string fileName = null; string fileName = null;
if (data != null && data.Data != null) if (data != null && data.Data != null)
{ {
if (data.Data.ToString()?.Contains(Constants.PACKAGE_NAME) != true) uri = data.Data;
{ fileName = AndroidHelpers.GetFileName(ApplicationContext, uri);
uri = data.Data;
fileName = AndroidHelpers.GetFileName(ApplicationContext, uri);
}
} }
else else
{ {
// camera // camera
var tmpDir = new Java.IO.File(FilesDir, Constants.TEMP_CAMERA_IMAGE_DIR); var file = new Java.IO.File(FilesDir, "temp_camera_photo.jpg");
var file = new Java.IO.File(tmpDir, Constants.TEMP_CAMERA_IMAGE_NAME);
uri = FileProvider.GetUriForFile(this, "com.x8bit.bitwarden.fileprovider", file); uri = FileProvider.GetUriForFile(this, "com.x8bit.bitwarden.fileprovider", file);
fileName = $"photo_{DateTime.UtcNow.ToString("yyyyMMddHHmmss")}.jpg"; fileName = $"photo_{DateTime.UtcNow.ToString("yyyyMMddHHmmss")}.jpg";
} }
if (uri == null || fileName == null) if (uri == null)
{ {
return; return;
} }

View File

@@ -12,6 +12,7 @@ using Bit.Core.Abstractions;
using Bit.Core.Services; using Bit.Core.Services;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Bit.Droid.Services; using Bit.Droid.Services;
using Plugin.CurrentActivity;
using Plugin.Fingerprint; using Plugin.Fingerprint;
using Xamarin.Android.Net; using Xamarin.Android.Net;
using System.Net.Http; using System.Net.Http;
@@ -20,11 +21,9 @@ using Bit.App.Utilities;
using Bit.App.Pages; using Bit.App.Pages;
using Bit.App.Utilities.AccountManagement; using Bit.App.Utilities.AccountManagement;
using Bit.App.Controls; using Bit.App.Controls;
using Bit.Core.Enums;
#if !FDROID #if !FDROID
using Android.Gms.Security; using Android.Gms.Security;
#endif #endif
using DeviceType = Bit.Core.Enums.DeviceType;
namespace Bit.Droid namespace Bit.Droid
{ {
@@ -35,9 +34,9 @@ namespace Bit.Droid
#endif #endif
[Register("com.x8bit.bitwarden.MainApplication")] [Register("com.x8bit.bitwarden.MainApplication")]
#if FDROID #if FDROID
public class MainApplication : MauiApplication public class MainApplication : Application
#else #else
public class MainApplication : MauiApplication, ProviderInstaller.IProviderInstallListener public class MainApplication : Application, ProviderInstaller.IProviderInstallListener
#endif #endif
{ {
public MainApplication(IntPtr handle, JniHandleOwnership transer) public MainApplication(IntPtr handle, JniHandleOwnership transer)
@@ -68,9 +67,9 @@ namespace Bit.Droid
ServiceContainer.Register<IDeleteAccountActionFlowExecutioner>("deleteAccountActionFlowExecutioner", deleteAccountActionFlowExecutioner); ServiceContainer.Register<IDeleteAccountActionFlowExecutioner>("deleteAccountActionFlowExecutioner", deleteAccountActionFlowExecutioner);
var verificationActionsFlowHelper = new VerificationActionsFlowHelper( var verificationActionsFlowHelper = new VerificationActionsFlowHelper(
ServiceContainer.Resolve<IKeyConnectorService>("keyConnectorService"),
ServiceContainer.Resolve<IPasswordRepromptService>("passwordRepromptService"), ServiceContainer.Resolve<IPasswordRepromptService>("passwordRepromptService"),
ServiceContainer.Resolve<ICryptoService>("cryptoService"), ServiceContainer.Resolve<ICryptoService>("cryptoService"));
ServiceContainer.Resolve<IUserVerificationService>());
ServiceContainer.Register<IVerificationActionsFlowHelper>("verificationActionsFlowHelper", verificationActionsFlowHelper); ServiceContainer.Register<IVerificationActionsFlowHelper>("verificationActionsFlowHelper", verificationActionsFlowHelper);
var accountsManager = new AccountsManager( var accountsManager = new AccountsManager(
@@ -94,12 +93,11 @@ namespace Bit.Droid
#endif #endif
} }
protected override MauiApp CreateMauiApp() => App.MauiProgram.CreateMauiApp();
public override void OnCreate() public override void OnCreate()
{ {
base.OnCreate(); base.OnCreate();
Bootstrap(); Bootstrap();
CrossCurrentActivity.Current.Init(this);
} }
public void OnProviderInstallFailed(int errorCode, Intent recoveryIntent) public void OnProviderInstallFailed(int errorCode, Intent recoveryIntent)
@@ -123,22 +121,22 @@ namespace Bit.Droid
ServiceContainer.Register("logger", logger); ServiceContainer.Register("logger", logger);
// Note: This might cause a race condition. Investigate more. // Note: This might cause a race condition. Investigate more.
//Task.Run(() => Task.Run(() =>
//{ {
// FFImageLoading.Forms.Platform.CachedImageRenderer.Init(true); FFImageLoading.Forms.Platform.CachedImageRenderer.Init(true);
// FFImageLoading.ImageService.Instance.Initialize(new FFImageLoading.Config.Configuration FFImageLoading.ImageService.Instance.Initialize(new FFImageLoading.Config.Configuration
// { {
// FadeAnimationEnabled = false, FadeAnimationEnabled = false,
// FadeAnimationForCachedImages = false, FadeAnimationForCachedImages = false,
// HttpClient = new HttpClient(new AndroidClientHandler() { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }) HttpClient = new HttpClient(new AndroidClientHandler() { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate })
// }); });
// ZXing.Net.Mobile.Forms.Android.Platform.Init(); ZXing.Net.Mobile.Forms.Android.Platform.Init();
//}); });
CrossFingerprint.SetCurrentActivityResolver(() => Microsoft.Maui.ApplicationModel.Platform.CurrentActivity); CrossFingerprint.SetCurrentActivityResolver(() => CrossCurrentActivity.Current.Activity);
var preferencesStorage = new PreferencesStorageService(null); var preferencesStorage = new PreferencesStorageService(null);
var localAppDataFolderPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData); var documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var liteDbStorage = new LiteDbStorageService(Path.Combine(localAppDataFolderPath, "bitwarden.db")); var liteDbStorage = new LiteDbStorageService(Path.Combine(documentsPath, "bitwarden.db"));
var localizeService = new LocalizeService(); var localizeService = new LocalizeService();
var broadcasterService = new BroadcasterService(logger); var broadcasterService = new BroadcasterService(logger);
var messagingService = new MobileBroadcasterMessagingService(broadcasterService); var messagingService = new MobileBroadcasterMessagingService(broadcasterService);
@@ -149,7 +147,7 @@ namespace Bit.Droid
var storageMediatorService = new StorageMediatorService(mobileStorageService, secureStorageService, preferencesStorage); var storageMediatorService = new StorageMediatorService(mobileStorageService, secureStorageService, preferencesStorage);
var stateService = new StateService(mobileStorageService, secureStorageService, storageMediatorService, messagingService); var stateService = new StateService(mobileStorageService, secureStorageService, storageMediatorService, messagingService);
var stateMigrationService = var stateMigrationService =
new StateMigrationService(Bit.Core.Enums.DeviceType.Android, liteDbStorage, preferencesStorage, secureStorageService); new StateMigrationService(liteDbStorage, preferencesStorage, secureStorageService);
var clipboardService = new ClipboardService(stateService); var clipboardService = new ClipboardService(stateService);
var deviceActionService = new DeviceActionService(stateService, messagingService); var deviceActionService = new DeviceActionService(stateService, messagingService);
var fileService = new FileService(stateService, broadcasterService); var fileService = new FileService(stateService, broadcasterService);
@@ -157,11 +155,10 @@ namespace Bit.Droid
messagingService, broadcasterService); messagingService, broadcasterService);
var autofillHandler = new AutofillHandler(stateService, messagingService, clipboardService, var autofillHandler = new AutofillHandler(stateService, messagingService, clipboardService,
platformUtilsService, new LazyResolve<IEventService>()); platformUtilsService, new LazyResolve<IEventService>());
var biometricService = new BiometricService();
var cryptoFunctionService = new PclCryptoFunctionService(cryptoPrimitiveService); var cryptoFunctionService = new PclCryptoFunctionService(cryptoPrimitiveService);
var cryptoService = new CryptoService(stateService, cryptoFunctionService, logger); var cryptoService = new CryptoService(stateService, cryptoFunctionService);
var biometricService = new BiometricService(stateService, cryptoService); var passwordRepromptService = new MobilePasswordRepromptService(platformUtilsService, cryptoService);
var userPinService = new UserPinService(stateService, cryptoService);
var passwordRepromptService = new MobilePasswordRepromptService(platformUtilsService, cryptoService, stateService);
ServiceContainer.Register<ISynchronousStorageService>(preferencesStorage); ServiceContainer.Register<ISynchronousStorageService>(preferencesStorage);
ServiceContainer.Register<IBroadcasterService>("broadcasterService", broadcasterService); ServiceContainer.Register<IBroadcasterService>("broadcasterService", broadcasterService);
@@ -184,7 +181,6 @@ namespace Bit.Droid
ServiceContainer.Register<ICryptoService>("cryptoService", cryptoService); ServiceContainer.Register<ICryptoService>("cryptoService", cryptoService);
ServiceContainer.Register<IPasswordRepromptService>("passwordRepromptService", passwordRepromptService); ServiceContainer.Register<IPasswordRepromptService>("passwordRepromptService", passwordRepromptService);
ServiceContainer.Register<IAvatarImageSourcePool>("avatarImageSourcePool", new AvatarImageSourcePool()); ServiceContainer.Register<IAvatarImageSourcePool>("avatarImageSourcePool", new AvatarImageSourcePool());
ServiceContainer.Register<IUserPinService>(userPinService);
// Push // Push
#if FDROID #if FDROID

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2024.3.1" android:installLocation="internalOnly" package="com.x8bit.bitwarden"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2023.3.3" android:installLocation="internalOnly" package="com.x8bit.bitwarden">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" /> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.NFC" /> <uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@@ -43,9 +43,6 @@
<!-- Support for Xamarin.Essentials.Browser.OpenAsync (for Android > 11) --> <!-- Support for Xamarin.Essentials.Browser.OpenAsync (for Android > 11) -->
<!-- Related docs: https://learn.microsoft.com/en-us/xamarin/essentials/open-browser?tabs=android --> <!-- Related docs: https://learn.microsoft.com/en-us/xamarin/essentials/open-browser?tabs=android -->
<queries> <queries>
<intent>
<action android:name="android.support.customtabs.action.CustomTabsService" />
</intent>
<intent> <intent>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<data android:scheme="http" /> <data android:scheme="http" />

View File

@@ -0,0 +1,28 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("BitwardenAndroid")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Bitwarden Inc.")]
[assembly: AssemblyProduct("Bitwarden")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -8,6 +8,7 @@ using Bit.Core.Utilities;
using Firebase.Messaging; using Firebase.Messaging;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Xamarin.Forms;
namespace Bit.Droid.Push namespace Bit.Droid.Push
{ {

View File

@@ -4,7 +4,7 @@ using Android.Content;
using Bit.App.Utilities; using Bit.App.Utilities;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Bit.App.Droid.Utilities; using Bit.Droid.Utilities;
namespace Bit.Droid.Receivers namespace Bit.Droid.Receivers
{ {

View File

@@ -0,0 +1,69 @@
using System.ComponentModel;
using Android.Content;
using Android.Content.Res;
using Android.Views.InputMethods;
using Bit.Droid.Renderers;
using Bit.Droid.Utilities;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(Editor), typeof(CustomEditorRenderer))]
namespace Bit.Droid.Renderers
{
public class CustomEditorRenderer : EditorRenderer
{
public CustomEditorRenderer(Context context)
: base(context)
{ }
// Workaround for issue described here:
// https://github.com/xamarin/Xamarin.Forms/issues/8291#issuecomment-617456651
protected override void OnAttachedToWindow()
{
base.OnAttachedToWindow();
EditText.Enabled = false;
EditText.Enabled = true;
}
protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
{
base.OnElementChanged(e);
UpdateBorderColor();
if (Control != null && e.NewElement != null)
{
Control.SetPadding(Control.PaddingLeft, Control.PaddingTop - 10, Control.PaddingRight,
Control.PaddingBottom + 20);
Control.ImeOptions = Control.ImeOptions | (ImeAction)ImeFlags.NoPersonalizedLearning |
(ImeAction)ImeFlags.NoExtractUi;
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == Entry.TextColorProperty.PropertyName)
{
UpdateBorderColor();
}
}
private void UpdateBorderColor()
{
if (Control != null)
{
var states = new[]
{
new[] { Android.Resource.Attribute.StateFocused }, // focused
new[] { -Android.Resource.Attribute.StateFocused }, // unfocused
};
var colors = new int[]
{
ThemeHelpers.PrimaryColor,
ThemeHelpers.MutedColor
};
Control.BackgroundTintList = new ColorStateList(states, colors);
}
}
}
}

View File

@@ -0,0 +1,107 @@
using System.ComponentModel;
using Android.Content;
using Android.Content.Res;
using Android.Graphics;
using Android.Text;
using Android.Views.InputMethods;
using Android.Widget;
using Bit.Droid.Renderers;
using Bit.Droid.Utilities;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(Entry), typeof(CustomEntryRenderer))]
namespace Bit.Droid.Renderers
{
public class CustomEntryRenderer : EntryRenderer
{
public CustomEntryRenderer(Context context)
: base(context)
{ }
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
UpdateBorderColor();
if (Control != null && e.NewElement != null)
{
Control.SetPadding(Control.PaddingLeft, Control.PaddingTop - 10, Control.PaddingRight,
Control.PaddingBottom + 20);
Control.ImeOptions = Control.ImeOptions | (ImeAction)ImeFlags.NoPersonalizedLearning |
(ImeAction)ImeFlags.NoExtractUi;
}
}
// Workaround for bug preventing long-press -> copy/paste on Android 11
// See https://issuetracker.google.com/issues/37095917
protected override void OnAttachedToWindow()
{
base.OnAttachedToWindow();
Control.Enabled = false;
Control.Enabled = true;
}
// Workaround for failure to disable text prediction on non-password fields
// see https://github.com/xamarin/Xamarin.Forms/issues/10857
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
// Check if changed property is "IsPassword", otherwise ignore
if (e.PropertyName == Entry.IsPasswordProperty.PropertyName)
{
// Check if field type is text, otherwise ignore (numeric passwords, etc.)
EditText.InputType = Element.Keyboard.ToInputType();
bool isText = (EditText.InputType & InputTypes.ClassText) == InputTypes.ClassText,
isNumber = (EditText.InputType & InputTypes.ClassNumber) == InputTypes.ClassNumber;
if (isText || isNumber)
{
if (Element.IsPassword)
{
// Element is a password field, set inputType to TextVariationPassword which disables
// predictive text by default
EditText.InputType = EditText.InputType |
(isText ? InputTypes.TextVariationPassword : InputTypes.NumberVariationPassword);
}
else
{
// Element is not a password field, set inputType to TextVariationVisiblePassword to
// disable predictive text while still displaying the content.
EditText.InputType = EditText.InputType |
(isText ? InputTypes.TextVariationVisiblePassword : InputTypes.NumberVariationNormal);
}
// The workaround above forces a reset of the style properties, so we need to re-apply the font.
// see https://xamarin.github.io/bugzilla-archives/33/33666/bug.html
var typeface = Typeface.CreateFromAsset(Context.Assets, "RobotoMono_Regular.ttf");
if (Control is TextView label)
{
label.Typeface = typeface;
}
}
}
else if (e.PropertyName == Entry.TextColorProperty.PropertyName)
{
UpdateBorderColor();
}
}
private void UpdateBorderColor()
{
if (Control != null)
{
var states = new[]
{
new[] { Android.Resource.Attribute.StateFocused }, // focused
new[] { -Android.Resource.Attribute.StateFocused }, // unfocused
};
var colors = new int[]
{
ThemeHelpers.PrimaryColor,
ThemeHelpers.MutedColor
};
Control.BackgroundTintList = new ColorStateList(states, colors);
}
}
}
}

View File

@@ -0,0 +1,31 @@
using System;
using Android.App;
using Android.Content;
using AndroidX.AppCompat.Widget;
using Bit.App.Resources;
using Bit.Droid.Renderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(ContentPage), typeof(CustomPageRenderer))]
namespace Bit.Droid.Renderers
{
public class CustomPageRenderer : PageRenderer
{
public CustomPageRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
{
base.OnElementChanged(e);
Activity context = (Activity)this.Context;
var toolbar = context.FindViewById<Toolbar>(Resource.Id.toolbar);
if(toolbar != null)
{
toolbar.NavigationContentDescription = AppResources.TapToGoBack;
}
}
}
}

View File

@@ -0,0 +1,57 @@
using System.ComponentModel;
using Android.Content;
using Android.Content.Res;
using Bit.Droid.Renderers;
using Bit.Droid.Utilities;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(Picker), typeof(CustomPickerRenderer))]
namespace Bit.Droid.Renderers
{
public class CustomPickerRenderer : PickerRenderer
{
public CustomPickerRenderer(Context context)
: base(context)
{ }
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
UpdateBorderColor();
if (Control != null && e.NewElement != null)
{
Control.SetPadding(Control.PaddingLeft, Control.PaddingTop - 10, Control.PaddingRight,
Control.PaddingBottom + 20);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == Picker.TextColorProperty.PropertyName)
{
UpdateBorderColor();
}
}
private void UpdateBorderColor()
{
if (Control != null)
{
var states = new[]
{
new[] { Android.Resource.Attribute.StateFocused }, // focused
new[] { -Android.Resource.Attribute.StateFocused }, // unfocused
};
var colors = new int[]
{
ThemeHelpers.PrimaryColor,
ThemeHelpers.MutedColor
};
Control.BackgroundTintList = new ColorStateList(states, colors);
}
}
}
}

View File

@@ -0,0 +1,33 @@
using Android.Content;
using Android.Views.InputMethods;
using Bit.Droid.Renderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(SearchBar), typeof(CustomSearchBarRenderer))]
namespace Bit.Droid.Renderers
{
public class CustomSearchBarRenderer : SearchBarRenderer
{
public CustomSearchBarRenderer(Context context)
: base(context)
{ }
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
{
base.OnElementChanged(e);
if (Control != null && e.NewElement != null)
{
try
{
var magId = Resources.GetIdentifier("android:id/search_mag_icon", null, null);
var magImage = (Android.Widget.ImageView)Control.FindViewById(magId);
magImage.LayoutParameters = new Android.Widget.LinearLayout.LayoutParams(0, 0);
}
catch { }
Control.SetImeOptions(Control.ImeOptions | (ImeAction)ImeFlags.NoPersonalizedLearning |
(ImeAction)ImeFlags.NoExtractUi);
}
}
}
}

View File

@@ -0,0 +1,67 @@
using System.ComponentModel;
using Android.Content;
using Android.Content.Res;
using Android.Graphics.Drawables;
using Android.OS;
using AndroidX.Core.Content.Resources;
using Bit.Droid.Renderers;
using Bit.Droid.Utilities;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(Switch), typeof(CustomSwitchRenderer))]
namespace Bit.Droid.Renderers
{
public class CustomSwitchRenderer : SwitchRenderer
{
public CustomSwitchRenderer(Context context)
: base(context)
{}
protected override void OnElementChanged(ElementChangedEventArgs<Switch> e)
{
base.OnElementChanged(e);
UpdateColors();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == Switch.OnColorProperty.PropertyName)
{
UpdateColors();
}
}
private void UpdateColors()
{
if (Build.VERSION.SdkInt <= BuildVersionCodes.LollipopMr1)
{
// Android 5.x doesn't support ThumbTintList, and using SwitchCompat on every version after 5.x
// doesn't apply tinting the way we want. Let 5.x to do its own thing here.
return;
}
if (Control != null)
{
Control.SetHintTextColor(ThemeHelpers.MutedColor);
var t = ResourcesCompat.GetDrawable(Resources, Resource.Drawable.switch_thumb, null);
if (t is GradientDrawable thumb)
{
Control.ThumbDrawable = thumb;
}
var thumbStates = new[]
{
new[] { Android.Resource.Attribute.StateChecked }, // checked
new[] { -Android.Resource.Attribute.StateChecked }, // unchecked
};
var thumbColors = new int[]
{
ThemeHelpers.SwitchOnColor,
ThemeHelpers.SwitchThumbColor
};
Control.ThumbTintList = new ColorStateList(thumbStates, thumbColors);
}
}
}
}

View File

@@ -0,0 +1,66 @@
using Android.Content;
using Android.Views;
using Bit.App.Pages;
using Bit.Droid.Renderers;
using Google.Android.Material.BottomNavigation;
using Google.Android.Material.Navigation;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Xamarin.Forms.Platform.Android.AppCompat;
[assembly: ExportRenderer(typeof(TabbedPage), typeof(CustomTabbedRenderer))]
namespace Bit.Droid.Renderers
{
public class CustomTabbedRenderer : TabbedPageRenderer, NavigationBarView.IOnItemReselectedListener
{
private TabbedPage _page;
public CustomTabbedRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
_page = e.NewElement;
GetBottomNavigationView()?.SetOnItemReselectedListener(this);
}
else
{
_page = e.OldElement;
}
}
private BottomNavigationView GetBottomNavigationView()
{
for (var i = 0; i < ViewGroup.ChildCount; i++)
{
var childView = ViewGroup.GetChildAt(i);
if (childView is ViewGroup viewGroup)
{
for (var j = 0; j < viewGroup.ChildCount; j++)
{
var childRelativeLayoutView = viewGroup.GetChildAt(j);
if (childRelativeLayoutView is BottomNavigationView bottomNavigationView)
{
return bottomNavigationView;
}
}
}
}
return null;
}
public void OnNavigationItemReselected(IMenuItem item)
{
if (_page?.CurrentPage?.Navigation != null && _page.CurrentPage.Navigation.NavigationStack.Count > 0)
{
if (_page is TabsPage tabsPage)
{
tabsPage.OnPageReselected();
}
Device.BeginInvokeOnMainThread(async () => await _page.CurrentPage.Navigation.PopToRootAsync());
}
}
}
}

View File

@@ -0,0 +1,50 @@
using System.ComponentModel;
using Android.Content;
using Android.Views;
using Bit.App.Controls;
using Bit.Droid.Renderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(ExtendedDatePicker), typeof(ExtendedDatePickerRenderer))]
namespace Bit.Droid.Renderers
{
public class ExtendedDatePickerRenderer : DatePickerRenderer
{
public ExtendedDatePickerRenderer(Context context)
: base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
{
base.OnElementChanged(e);
if (Control != null && Element is ExtendedDatePicker element)
{
// center text
Control.Gravity = GravityFlags.CenterHorizontal;
// use placeholder until NullableDate set
if (!element.NullableDate.HasValue)
{
Control.Text = element.PlaceHolder;
}
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == DatePicker.DateProperty.PropertyName ||
e.PropertyName == DatePicker.FormatProperty.PropertyName)
{
if (Control != null && Element is ExtendedDatePicker element)
{
if (Element.Format == element.PlaceHolder)
{
Control.Text = element.PlaceHolder;
return;
}
}
}
base.OnElementPropertyChanged(sender, e);
}
}
}

View File

@@ -0,0 +1,23 @@
using Android.Content;
using Bit.App.Controls;
using Bit.Droid.Renderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(ExtendedGrid), typeof(ExtendedGridRenderer))]
namespace Bit.Droid.Renderers
{
public class ExtendedGridRenderer : ViewRenderer
{
public ExtendedGridRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<View> elementChangedEvent)
{
base.OnElementChanged(elementChangedEvent);
if (elementChangedEvent.NewElement != null)
{
SetBackgroundResource(Resource.Drawable.list_item_bg);
}
}
}
}

View File

@@ -0,0 +1,56 @@
using System.ComponentModel;
using Android.Content;
using Android.Graphics.Drawables;
using AndroidX.Core.Content.Resources;
using Bit.App.Controls;
using Bit.Droid.Renderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(ExtendedSlider), typeof(ExtendedSliderRenderer))]
namespace Bit.Droid.Renderers
{
public class ExtendedSliderRenderer : SliderRenderer
{
public ExtendedSliderRenderer(Context context)
: base(context)
{}
protected override void OnElementChanged(ElementChangedEventArgs<Slider> e)
{
base.OnElementChanged(e);
UpdateColor();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == ExtendedSlider.ThumbBorderColorProperty.PropertyName)
{
UpdateColor();
}
}
private void UpdateColor()
{
if (Control != null && Element is ExtendedSlider view)
{
var t = ResourcesCompat.GetDrawable(Resources, Resource.Drawable.slider_thumb, null);
if (t is GradientDrawable thumb)
{
if (view.ThumbColor == Color.Default)
{
thumb.SetColor(Color.White.ToAndroid());
}
else
{
thumb.SetColor(view.ThumbColor.ToAndroid());
}
thumb.SetStroke(3, view.ThumbBorderColor.ToAndroid());
Control.SetThumb(thumb);
}
}
}
}
}

View File

@@ -0,0 +1,23 @@
using Android.Content;
using Bit.App.Controls;
using Bit.Droid.Renderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(ExtendedStackLayout), typeof(ExtendedStackLayoutRenderer))]
namespace Bit.Droid.Renderers
{
public class ExtendedStackLayoutRenderer : ViewRenderer
{
public ExtendedStackLayoutRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<View> elementChangedEvent)
{
base.OnElementChanged(elementChangedEvent);
if (elementChangedEvent.NewElement != null)
{
SetBackgroundResource(Resource.Drawable.list_item_bg);
}
}
}
}

View File

@@ -0,0 +1,72 @@
using System.ComponentModel;
using Android.Content;
using Android.Graphics;
using Android.OS;
using Bit.App.Controls;
using Bit.Droid.Renderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(ExtendedStepper), typeof(ExtendedStepperRenderer))]
namespace Bit.Droid.Renderers
{
public class ExtendedStepperRenderer : StepperRenderer
{
public ExtendedStepperRenderer(Context context)
: base(context)
{}
protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
{
base.OnElementChanged(e);
UpdateBgColor();
UpdateFgColor();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == ExtendedStepper.StepperBackgroundColorProperty.PropertyName)
{
UpdateBgColor();
}
else if (e.PropertyName == ExtendedStepper.StepperForegroundColorProperty.PropertyName)
{
UpdateFgColor();
}
}
private void UpdateBgColor()
{
if (Control != null && Element is ExtendedStepper view)
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.Q)
{
Control.GetChildAt(0)?.Background?.SetColorFilter(
new BlendModeColorFilter(view.StepperBackgroundColor.ToAndroid(), BlendMode.Multiply));
Control.GetChildAt(1)?.Background?.SetColorFilter(
new BlendModeColorFilter(view.StepperBackgroundColor.ToAndroid(), BlendMode.Multiply));
}
else
{
Control.GetChildAt(0)?.Background?.SetColorFilter(
view.StepperBackgroundColor.ToAndroid(), PorterDuff.Mode.Multiply);
Control.GetChildAt(1)?.Background?.SetColorFilter(
view.StepperBackgroundColor.ToAndroid(), PorterDuff.Mode.Multiply);
}
}
}
private void UpdateFgColor()
{
if (Control != null && Element is ExtendedStepper view)
{
var btn0 = Control.GetChildAt(0) as Android.Widget.Button;
btn0?.SetTextColor(view.StepperForegroundColor.ToAndroid());
var btn1 = Control.GetChildAt(1) as Android.Widget.Button;
btn1?.SetTextColor(view.StepperForegroundColor.ToAndroid());
}
}
}
}

View File

@@ -0,0 +1,50 @@
using System.ComponentModel;
using Android.Content;
using Android.Views;
using Bit.App.Controls;
using Bit.Droid.Renderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(ExtendedTimePicker), typeof(ExtendedTimePickerRenderer))]
namespace Bit.Droid.Renderers
{
public class ExtendedTimePickerRenderer : TimePickerRenderer
{
public ExtendedTimePickerRenderer(Context context)
: base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e)
{
base.OnElementChanged(e);
if (Control != null && Element is ExtendedTimePicker element)
{
// center text
Control.Gravity = GravityFlags.CenterHorizontal;
// use placeholder until NullableTime set
if (!element.NullableTime.HasValue)
{
Control.Text = element.PlaceHolder;
}
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == TimePicker.TimeProperty.PropertyName ||
e.PropertyName == TimePicker.FormatProperty.PropertyName)
{
if (Control != null && Element is ExtendedTimePicker element)
{
if (Element.Format == element.PlaceHolder)
{
Control.Text = element.PlaceHolder;
return;
}
}
}
base.OnElementPropertyChanged(sender, e);
}
}
}

View File

@@ -0,0 +1,98 @@
using System;
using Bit.App.Controls;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Android.Webkit;
using AWebkit = Android.Webkit;
using Java.Interop;
using Android.Content;
using Bit.Droid.Renderers;
using System.ComponentModel;
[assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace Bit.Droid.Renderers
{
public class HybridWebViewRenderer : ViewRenderer<HybridWebView, AWebkit.WebView>
{
private const string JSFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}";
private readonly Context _context;
public HybridWebViewRenderer(Context context)
: base(context)
{
_context = context;
}
protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
var webView = new AWebkit.WebView(_context);
webView.Settings.JavaScriptEnabled = true;
webView.SetWebViewClient(new JSWebViewClient(string.Format("javascript: {0}", JSFunction)));
SetNativeControl(webView);
}
if (e.OldElement != null)
{
Control.RemoveJavascriptInterface("jsBridge");
var hybridWebView = e.OldElement as HybridWebView;
hybridWebView.Cleanup();
}
if (e.NewElement != null)
{
Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
Control.LoadUrl(Element.Uri);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == HybridWebView.UriProperty.PropertyName)
{
Control.LoadUrl(Element.Uri);
}
}
public class JSBridge : Java.Lang.Object
{
private readonly WeakReference<HybridWebViewRenderer> _hybridWebViewRenderer;
public JSBridge(HybridWebViewRenderer hybridRenderer)
{
_hybridWebViewRenderer = new WeakReference<HybridWebViewRenderer>(hybridRenderer);
}
[JavascriptInterface]
[Export("invokeAction")]
public void InvokeAction(string data)
{
if (_hybridWebViewRenderer != null &&
_hybridWebViewRenderer.TryGetTarget(out HybridWebViewRenderer hybridRenderer))
{
hybridRenderer.Element.InvokeAction(data);
}
}
}
public class JSWebViewClient : WebViewClient
{
private readonly string _javascript;
public JSWebViewClient(string javascript)
{
_javascript = javascript;
}
public override void OnPageFinished(AWebkit.WebView view, string url)
{
base.OnPageFinished(view, url);
view.EvaluateJavascript(_javascript, null);
}
}
}
}

View File

@@ -0,0 +1,25 @@
using System;
using Android.Content;
using Bit.App.Controls;
using Bit.Droid.Renderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(SelectableLabel), typeof(SelectableLabelRenderer))]
namespace Bit.Droid.Renderers
{
public class SelectableLabelRenderer : LabelRenderer
{
public SelectableLabelRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.SetTextIsSelectable(true);
}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Some files were not shown because too many files have changed in this diff Show More