main 2578da419092 cached
643 files
2.9 MB
799.7k tokens
14 symbols
1 requests
Download .txt
Showing preview only (3,212K chars total). Download the full file or copy to clipboard to get everything.
Repository: admin-ch/CovidCertificate-App-Android
Branch: main
Commit: 2578da419092
Files: 643
Total size: 2.9 MB

Directory structure:
gitextract_e7z7c8gy/

├── .github/
│   ├── actions/
│   │   └── gradle_docker/
│   │       ├── action.yml
│   │       └── main.sh
│   └── workflows/
│       ├── appcenter_verifier_abn.yml
│       ├── appcenter_verifier_dev.yml
│       ├── appcenter_verifier_prod.yml
│       ├── appcenter_verifier_prodfdroid.yml
│       ├── appcenter_wallet_abn.yml
│       ├── appcenter_wallet_dev.yml
│       ├── appcenter_wallet_prod.yml
│       ├── appcenter_wallet_prodfdroid.yml
│       ├── browserstack_wallet_abn.yml
│       ├── build.yml
│       └── gradle-wrapper-validation.yml
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── REPRODUCIBLE_BUILDS.md
├── apkdiff.py
├── build.gradle
├── buildAndCompare.sh
├── common/
│   ├── .gitignore
│   ├── build.gradle
│   ├── consumer-rules.pro
│   ├── proguard-rules.pro
│   └── src/
│       ├── abn/
│       │   └── java/
│       │       └── ch/
│       │           └── admin/
│       │               └── bag/
│       │                   └── covidcertificate/
│       │                       └── common/
│       │                           └── debug/
│       │                               └── DebugFragment.kt
│       ├── dev/
│       │   ├── java/
│       │   │   └── ch/
│       │   │       └── admin/
│       │   │           └── bag/
│       │   │               └── covidcertificate/
│       │   │                   └── common/
│       │   │                       └── debug/
│       │   │                           ├── DebugFragment.kt
│       │   │                           └── DebugSecureStorage.kt
│       │   └── res/
│       │       └── xml/
│       │           └── network_security_config.xml
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── assets/
│       │   │   └── impressum/
│       │   │       ├── de/
│       │   │       │   ├── impressum.html
│       │   │       │   └── licence.html
│       │   │       ├── en/
│       │   │       │   ├── impressum.html
│       │   │       │   └── licence.html
│       │   │       ├── fonts/
│       │   │       │   ├── Inter-Bold.otf
│       │   │       │   └── Inter-Light.otf
│       │   │       ├── fr/
│       │   │       │   ├── impressum.html
│       │   │       │   └── licence.html
│       │   │       ├── it/
│       │   │       │   ├── impressum.html
│       │   │       │   └── licence.html
│       │   │       └── rm/
│       │   │           ├── impressum.html
│       │   │           └── licence.html
│       │   ├── java/
│       │   │   └── ch/
│       │   │       └── admin/
│       │   │           └── bag/
│       │   │               └── covidcertificate/
│       │   │                   └── common/
│       │   │                       ├── BaseActivity.kt
│       │   │                       ├── browserstack/
│       │   │                       │   ├── AirplaneMode.kt
│       │   │                       │   ├── BadNetwork.kt
│       │   │                       │   ├── Normal.kt
│       │   │                       │   └── Onboarding.kt
│       │   │                       ├── config/
│       │   │                       │   ├── CertificateRenewalInfoDetailModel.kt
│       │   │                       │   ├── CertificateRenewalInfoModel.kt
│       │   │                       │   ├── CertificateRenewalType.kt
│       │   │                       │   ├── CheckModesInfosModel.kt
│       │   │                       │   ├── ConfigModel.kt
│       │   │                       │   ├── ConfigViewModel.kt
│       │   │                       │   ├── CovidCertificateNewsItem.kt
│       │   │                       │   ├── EolBannerInfoModel.kt
│       │   │                       │   ├── FaqEntryModel.kt
│       │   │                       │   ├── FaqIntroSection.kt
│       │   │                       │   ├── FaqModel.kt
│       │   │                       │   ├── ForeignRulesHintModel.kt
│       │   │                       │   ├── InfoBoxModel.kt
│       │   │                       │   ├── InfoCovidCertificateNews.kt
│       │   │                       │   ├── RefreshButtonInfoModel.kt
│       │   │                       │   ├── VaccinationBookingInfoModel.kt
│       │   │                       │   └── VaccinationHintModel.kt
│       │   │                       ├── data/
│       │   │                       │   └── ConfigSecureStorage.kt
│       │   │                       ├── dialog/
│       │   │                       │   └── InfoDialogFragment.kt
│       │   │                       ├── exception/
│       │   │                       │   ├── HttpIOException.kt
│       │   │                       │   └── TimeDeviationException.kt
│       │   │                       ├── extensions/
│       │   │                       │   ├── ContextExtensions.kt
│       │   │                       │   ├── DccCertExtensions.kt
│       │   │                       │   ├── LifecycleOwnerExtensions.kt
│       │   │                       │   ├── OkHttpExtensions.kt
│       │   │                       │   └── WindowExtensions.kt
│       │   │                       ├── faq/
│       │   │                       │   ├── FaqAdapter.kt
│       │   │                       │   ├── FaqFragment.kt
│       │   │                       │   ├── FaqItem.kt
│       │   │                       │   ├── FaqViewHolder.kt
│       │   │                       │   └── model/
│       │   │                       │       └── Header.kt
│       │   │                       ├── html/
│       │   │                       │   ├── BuildInfo.kt
│       │   │                       │   └── ImprintFragment.kt
│       │   │                       ├── net/
│       │   │                       │   ├── ConfigRepository.kt
│       │   │                       │   └── ConfigService.kt
│       │   │                       ├── onboarding/
│       │   │                       │   ├── BaseOnboardingActivity.kt
│       │   │                       │   └── SimpleOnboardingPagerAdapter.kt
│       │   │                       ├── qr/
│       │   │                       │   ├── CameraPermissionExplanationDialog.kt
│       │   │                       │   ├── KittlerBinarizer.kt
│       │   │                       │   ├── QRCodeReaderHelper.kt
│       │   │                       │   ├── QrScanFragment.kt
│       │   │                       │   └── QrScannerState.kt
│       │   │                       ├── settings/
│       │   │                       │   └── SettingsFragment.kt
│       │   │                       ├── util/
│       │   │                       │   ├── AssetUtil.kt
│       │   │                       │   ├── CutOutEdgeTreatment.kt
│       │   │                       │   ├── EnvironmentUtil.kt
│       │   │                       │   ├── ErrorCodeUtil.kt
│       │   │                       │   ├── ErrorHelper.kt
│       │   │                       │   ├── ErrorState.kt
│       │   │                       │   ├── HorizontalMarginItemDecoration.kt
│       │   │                       │   ├── LocaleUtil.kt
│       │   │                       │   ├── SingleLiveEvent.java
│       │   │                       │   ├── StringUtil.kt
│       │   │                       │   ├── UiUtil.kt
│       │   │                       │   ├── UlTagHandler.java
│       │   │                       │   └── UrlUtil.java
│       │   │                       └── views/
│       │   │                           ├── MarginItemDecoration.kt
│       │   │                           ├── ViewExtensions.kt
│       │   │                           └── WindowInsetsLayout.kt
│       │   └── res/
│       │       ├── anim/
│       │       │   ├── fragment_open_enter.xml
│       │       │   ├── fragment_open_exit.xml
│       │       │   ├── slide_enter.xml
│       │       │   ├── slide_exit.xml
│       │       │   ├── slide_pop_enter.xml
│       │       │   └── slide_pop_exit.xml
│       │       ├── color/
│       │       │   ├── selector_black_or_white.xml
│       │       │   ├── selector_blue_or_white.xml
│       │       │   ├── selector_grey_or_blue.xml
│       │       │   ├── selector_grey_or_white.xml
│       │       │   ├── selector_transparent_or_blue.xml
│       │       │   ├── selector_white_or_black.xml
│       │       │   ├── selector_white_or_blue.xml
│       │       │   └── text_radio_checkable.xml
│       │       ├── drawable/
│       │       │   ├── bg_button_default.xml
│       │       │   ├── bg_button_red.xml
│       │       │   ├── bg_button_white.xml
│       │       │   ├── bg_corners_top_left.xml
│       │       │   ├── bg_dialog.xml
│       │       │   ├── bg_pill.xml
│       │       │   ├── bg_rect_rounded_sheet.xml
│       │       │   ├── bg_rect_rounded_small.xml
│       │       │   ├── bg_rect_rounded_small_blue_ripple.xml
│       │       │   ├── bg_rect_rounded_small_checkable.xml
│       │       │   ├── bg_rect_rounded_small_red.xml
│       │       │   ├── btn_radio_checkable.xml
│       │       │   ├── dot_black.xml
│       │       │   ├── dot_grey.xml
│       │       │   ├── dot_white.xml
│       │       │   ├── header_bottom.xml
│       │       │   ├── header_collapsed_shadow.xml
│       │       │   ├── ic_1g.xml
│       │       │   ├── ic_2g.xml
│       │       │   ├── ic_2g_green.xml
│       │       │   ├── ic_2g_grey.xml
│       │       │   ├── ic_2g_plus.xml
│       │       │   ├── ic_3g.xml
│       │       │   ├── ic_arrow_contract.xml
│       │       │   ├── ic_arrow_expand.xml
│       │       │   ├── ic_arrow_forward.xml
│       │       │   ├── ic_bund_small.xml
│       │       │   ├── ic_bundwappen_big.xml
│       │       │   ├── ic_call.xml
│       │       │   ├── ic_cam_off.xml
│       │       │   ├── ic_camera_switch.xml
│       │       │   ├── ic_check_filled.xml
│       │       │   ├── ic_check_green.xml
│       │       │   ├── ic_check_grey.xml
│       │       │   ├── ic_check_large.xml
│       │       │   ├── ic_checkbox_empty.xml
│       │       │   ├── ic_checkbox_filled.xml
│       │       │   ├── ic_close.xml
│       │       │   ├── ic_close_red.xml
│       │       │   ├── ic_dot.xml
│       │       │   ├── ic_double_check.xml
│       │       │   ├── ic_error.xml
│       │       │   ├── ic_error_blue.xml
│       │       │   ├── ic_error_grey.xml
│       │       │   ├── ic_error_large.xml
│       │       │   ├── ic_error_orange.xml
│       │       │   ├── ic_error_triangle.xml
│       │       │   ├── ic_expire_i.xml
│       │       │   ├── ic_faq.xml
│       │       │   ├── ic_header_slim.xml
│       │       │   ├── ic_how_it_works_image.xml
│       │       │   ├── ic_info.xml
│       │       │   ├── ic_info_alert.xml
│       │       │   ├── ic_info_blue.xml
│       │       │   ├── ic_info_outline.xml
│       │       │   ├── ic_invalid_grey.xml
│       │       │   ├── ic_invalid_red.xml
│       │       │   ├── ic_light_off.xml
│       │       │   ├── ic_light_off_blue.xml
│       │       │   ├── ic_light_on.xml
│       │       │   ├── ic_light_on_black.xml
│       │       │   ├── ic_link_external.xml
│       │       │   ├── ic_load.xml
│       │       │   ├── ic_no1g.xml
│       │       │   ├── ic_no2g.xml
│       │       │   ├── ic_no3g.xml
│       │       │   ├── ic_no_2_g_plus_height.xml
│       │       │   ├── ic_no_connection.xml
│       │       │   ├── ic_no_connection_large.xml
│       │       │   ├── ic_notification.xml
│       │       │   ├── ic_notification_filled.xml
│       │       │   ├── ic_offline.xml
│       │       │   ├── ic_offline_large.xml
│       │       │   ├── ic_offline_orange.xml
│       │       │   ├── ic_one.xml
│       │       │   ├── ic_phone.xml
│       │       │   ├── ic_plus.xml
│       │       │   ├── ic_plus_green.xml
│       │       │   ├── ic_privacy.xml
│       │       │   ├── ic_privacy_grey.xml
│       │       │   ├── ic_process_error.xml
│       │       │   ├── ic_process_error_grey.xml
│       │       │   ├── ic_process_error_large.xml
│       │       │   ├── ic_qr_certificate_light.xml
│       │       │   ├── ic_qr_certificate_light_no.xml
│       │       │   ├── ic_question_outline.xml
│       │       │   ├── ic_retry.xml
│       │       │   ├── ic_scanner_alert.xml
│       │       │   ├── ic_scanner_alert_white.xml
│       │       │   ├── ic_settings.xml
│       │       │   ├── ic_t.xml
│       │       │   ├── ic_three.xml
│       │       │   ├── ic_timeerror.xml
│       │       │   ├── ic_timeerror_large.xml
│       │       │   ├── ic_timeerror_orange.xml
│       │       │   ├── ic_timelapse.xml
│       │       │   ├── ic_timelapse_blue.xml
│       │       │   ├── ic_timelapse_red.xml
│       │       │   ├── ic_travel.xml
│       │       │   ├── ic_two.xml
│       │       │   ├── ic_zoom_off.xml
│       │       │   ├── ic_zoom_off_white.xml
│       │       │   ├── ic_zoom_on.xml
│       │       │   ├── ic_zoom_on_black.xml
│       │       │   ├── illu_onboarding_data_protection.xml
│       │       │   ├── line_dashed_grey.xml
│       │       │   ├── qr_scanner_bottom_left.xml
│       │       │   ├── qr_scanner_bottom_right.xml
│       │       │   ├── qr_scanner_top_left.xml
│       │       │   ├── qr_scanner_top_right.xml
│       │       │   ├── ripple_rect.xml
│       │       │   ├── ripple_rounded.xml
│       │       │   ├── ripple_rounded_button.xml
│       │       │   ├── ripple_rounded_rect.xml
│       │       │   ├── ripple_rounded_rect_banner.xml
│       │       │   ├── ripple_rounded_rect_small.xml
│       │       │   ├── tab_selector.xml
│       │       │   └── tab_selector_white.xml
│       │       ├── font/
│       │       │   └── inter.xml
│       │       ├── layout/
│       │       │   ├── activity_onboarding.xml
│       │       │   ├── dialog_camera_permission_explanation.xml
│       │       │   ├── dialog_fragment_info_box.xml
│       │       │   ├── fragment_debug.xml
│       │       │   ├── fragment_faq.xml
│       │       │   ├── fragment_html.xml
│       │       │   ├── fragment_settings.xml
│       │       │   ├── item_error_status.xml
│       │       │   ├── item_faq_header.xml
│       │       │   ├── item_faq_intro_section.xml
│       │       │   ├── item_faq_question.xml
│       │       │   ├── item_header.xml
│       │       │   └── item_language_option.xml
│       │       ├── menu/
│       │       │   └── imprint.xml
│       │       ├── values/
│       │       │   ├── attrs.xml
│       │       │   ├── colors.xml
│       │       │   ├── dimens.xml
│       │       │   ├── strings.xml
│       │       │   └── styles.xml
│       │       ├── values-de/
│       │       │   └── strings.xml
│       │       ├── values-fr/
│       │       │   └── strings.xml
│       │       ├── values-it/
│       │       │   └── strings.xml
│       │       ├── values-rm/
│       │       │   └── strings.xml
│       │       └── xml/
│       │           └── network_security_config.xml
│       └── prod/
│           └── java/
│               └── ch/
│                   └── admin/
│                       └── bag/
│                           └── covidcertificate/
│                               └── common/
│                                   └── debug/
│                                       └── DebugFragment.kt
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── loadConfigs.sh
├── settings.gradle
├── verifier/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   ├── src/
│   │   ├── abn/
│   │   │   └── assets/
│   │   │       └── faq/
│   │   │           └── config.json
│   │   ├── dev/
│   │   │   └── assets/
│   │   │       └── faq/
│   │   │           └── config.json
│   │   └── main/
│   │       ├── AndroidManifest.xml
│   │       ├── assets/
│   │       │   └── faq/
│   │       │       └── config.json
│   │       ├── java/
│   │       │   └── ch/
│   │       │       └── admin/
│   │       │           └── bag/
│   │       │               └── covidcertificate/
│   │       │                   └── verifier/
│   │       │                       ├── HomeFragment.kt
│   │       │                       ├── MainActivity.kt
│   │       │                       ├── MainApplication.kt
│   │       │                       ├── data/
│   │       │                       │   └── VerifierSecureStorage.kt
│   │       │                       ├── extensions/
│   │       │                       │   └── ContextExtensions.kt
│   │       │                       ├── faq/
│   │       │                       │   └── VerifierFaqFragment.kt
│   │       │                       ├── modes/
│   │       │                       │   ├── ChooseModeDialogFragment.kt
│   │       │                       │   └── ModesAndConfigViewModel.kt
│   │       │                       ├── news/
│   │       │                       │   └── InfoCertificateNewsFragment.kt
│   │       │                       ├── pager/
│   │       │                       │   ├── HomescreenPageAdapter.kt
│   │       │                       │   └── HomescreenPagerFragment.kt
│   │       │                       ├── qr/
│   │       │                       │   └── VerifierQrScanFragment.kt
│   │       │                       ├── updateboarding/
│   │       │                       │   ├── UpdateboardingActivity.kt
│   │       │                       │   ├── UpdateboardingAgbFragment.kt
│   │       │                       │   └── UpdateboardingCertificateLightFragment.kt
│   │       │                       ├── verification/
│   │       │                       │   ├── VerificationAdapter.kt
│   │       │                       │   ├── VerificationFragment.kt
│   │       │                       │   ├── VerificationItem.kt
│   │       │                       │   ├── VerificationStateUtil.kt
│   │       │                       │   ├── VerificationViewHolder.kt
│   │       │                       │   └── VerificationViewModel.kt
│   │       │                       └── zebra/
│   │       │                           ├── ZebraActionBroadcastReceiver.kt
│   │       │                           ├── ZebraDataWedgeApiUtil.kt
│   │       │                           └── ZebraResultActionBroadcastReceiver.kt
│   │       ├── play/
│   │       │   ├── listings/
│   │       │   │   ├── de-DE/
│   │       │   │   │   ├── full-description.txt
│   │       │   │   │   ├── short-description.txt
│   │       │   │   │   └── title.txt
│   │       │   │   ├── en-US/
│   │       │   │   │   ├── full-description.txt
│   │       │   │   │   ├── short-description.txt
│   │       │   │   │   └── title.txt
│   │       │   │   ├── fr-FR/
│   │       │   │   │   ├── full-description.txt
│   │       │   │   │   ├── short-description.txt
│   │       │   │   │   └── title.txt
│   │       │   │   └── it-IT/
│   │       │   │       ├── full-description.txt
│   │       │   │       ├── short-description.txt
│   │       │   │       └── title.txt
│   │       │   └── release-notes/
│   │       │       └── en-US/
│   │       │           └── default.txt
│   │       └── res/
│   │           ├── drawable/
│   │           │   ├── bg_bubble_bottom_left.xml
│   │           │   ├── ic_faq_image.xml
│   │           │   ├── ic_header_2g_off.xml
│   │           │   ├── ic_header_2g_on.xml
│   │           │   ├── ic_header_plus_off.xml
│   │           │   ├── ic_header_plus_on.xml
│   │           │   ├── ic_illu_home_1.xml
│   │           │   ├── ic_illu_home_2.xml
│   │           │   ├── ic_launcher_background.xml
│   │           │   ├── ic_settings.xml
│   │           │   └── illu_updateboarding_certificate_light.xml
│   │           ├── layout/
│   │           │   ├── activity_main.xml
│   │           │   ├── dialog_fragment_choose_mode.xml
│   │           │   ├── dialog_fragment_info_certificate_news.xml
│   │           │   ├── fragment_home.xml
│   │           │   ├── fragment_home_screen_pager.xml
│   │           │   ├── fragment_qr_scan.xml
│   │           │   ├── fragment_updateboarding_agb.xml
│   │           │   ├── fragment_updateboarding_certificate_light.xml
│   │           │   ├── fragment_verification.xml
│   │           │   ├── item_certificate_news.xml
│   │           │   ├── item_mode_button.xml
│   │           │   ├── item_mode_info.xml
│   │           │   ├── item_progress_indicator.xml
│   │           │   ├── item_verification_header_icon.xml
│   │           │   ├── item_verification_status.xml
│   │           │   └── item_verification_status_info.xml
│   │           └── mipmap-anydpi-v26/
│   │               ├── ic_launcher.xml
│   │               └── ic_launcher_round.xml
│   └── testKeystore
└── wallet/
    ├── .gitignore
    ├── build.gradle
    ├── proguard-rules.pro
    ├── src/
    │   ├── abn/
    │   │   ├── assets/
    │   │   │   └── faq/
    │   │   │       └── config.json
    │   │   └── java/
    │   │       └── ch/
    │   │           └── admin/
    │   │               └── bag/
    │   │                   └── covidcertificate/
    │   │                       └── wallet/
    │   │                           └── debug/
    │   │                               └── WalletDebugFragment.kt
    │   ├── androidTest/
    │   │   └── java/
    │   │       └── ch/
    │   │           └── admin/
    │   │               └── bag/
    │   │                   └── covidcertificate/
    │   │                       └── wallet/
    │   │                           ├── EspressoUtil.kt
    │   │                           ├── LoadconfigTest.kt
    │   │                           ├── NestedScrollViewScrollTo.kt
    │   │                           ├── OnboardingTest.kt
    │   │                           ├── RecyclerViewNotEmptyAssertion.kt
    │   │                           ├── ScanCountTest.kt
    │   │                           ├── TransferCodeTest.kt
    │   │                           └── WaitUntilVisibleAction.kt
    │   ├── dev/
    │   │   ├── assets/
    │   │   │   └── faq/
    │   │   │       └── config.json
    │   │   └── java/
    │   │       └── ch/
    │   │           └── admin/
    │   │               └── bag/
    │   │                   └── covidcertificate/
    │   │                       └── wallet/
    │   │                           └── debug/
    │   │                               ├── DebugCertificateItem.kt
    │   │                               ├── DebugCertificatesListAdapter.kt
    │   │                               ├── DebugCertificatesListViewHolder.kt
    │   │                               └── WalletDebugFragment.kt
    │   ├── main/
    │   │   ├── AndroidManifest.xml
    │   │   ├── assets/
    │   │   │   └── faq/
    │   │   │       └── config.json
    │   │   ├── java/
    │   │   │   └── ch/
    │   │   │       └── admin/
    │   │   │           └── bag/
    │   │   │               └── covidcertificate/
    │   │   │                   └── wallet/
    │   │   │                       ├── CertificatesAndConfigViewModel.kt
    │   │   │                       ├── DeeplinkViewModel.kt
    │   │   │                       ├── MainActivity.kt
    │   │   │                       ├── MainApplication.kt
    │   │   │                       ├── add/
    │   │   │                       │   └── CertificateAddFragment.kt
    │   │   │                       ├── data/
    │   │   │                       │   ├── CertificateStorage.kt
    │   │   │                       │   ├── WalletDataItem.kt
    │   │   │                       │   ├── WalletDataSecureStorage.kt
    │   │   │                       │   ├── WalletSecureStorage.kt
    │   │   │                       │   └── adapter/
    │   │   │                       │       └── InstantJsonAdapter.kt
    │   │   │                       ├── detail/
    │   │   │                       │   ├── CertificateDetailAdapter.kt
    │   │   │                       │   ├── CertificateDetailFragment.kt
    │   │   │                       │   ├── CertificateDetailItem.kt
    │   │   │                       │   ├── CertificateDetailItemListBuilder.kt
    │   │   │                       │   └── CertificateDetailViewHolder.kt
    │   │   │                       ├── dialog/
    │   │   │                       │   ├── CertificateBannerInfoDialogFragment.kt
    │   │   │                       │   ├── ModeInfoDialogFragment.kt
    │   │   │                       │   └── RefreshButtonInfoDialogFragment.kt
    │   │   │                       ├── faq/
    │   │   │                       │   └── WalletFaqFragment.kt
    │   │   │                       ├── homescreen/
    │   │   │                       │   ├── HomeFragment.kt
    │   │   │                       │   └── pager/
    │   │   │                       │       ├── CertificatePagerFragment.kt
    │   │   │                       │       ├── CertificatesPagerAdapter.kt
    │   │   │                       │       ├── PagerDiffUtil.kt
    │   │   │                       │       ├── StatefulWalletItem.kt
    │   │   │                       │       ├── TransferCodePagerFragment.kt
    │   │   │                       │       └── WalletItem.kt
    │   │   │                       ├── howto/
    │   │   │                       │   └── HowToScanFragment.kt
    │   │   │                       ├── light/
    │   │   │                       │   ├── CertificateLightConversionFragment.kt
    │   │   │                       │   ├── CertificateLightDetailFragment.kt
    │   │   │                       │   ├── CertificateLightErrorCodes.kt
    │   │   │                       │   ├── CertificateLightPagerFragment.kt
    │   │   │                       │   ├── CertificateLightViewModel.kt
    │   │   │                       │   ├── model/
    │   │   │                       │   │   ├── CertificateLightConversionResponse.kt
    │   │   │                       │   │   └── CertificateLightConversionState.kt
    │   │   │                       │   └── net/
    │   │   │                       │       ├── CertificateLightRepository.kt
    │   │   │                       │       ├── CertificateLightRequestBody.kt
    │   │   │                       │       ├── CertificateLightResponse.kt
    │   │   │                       │       └── CertificateLightService.kt
    │   │   │                       ├── list/
    │   │   │                       │   ├── CertificatesListFragment.kt
    │   │   │                       │   ├── CertificatesListTouchHelper.kt
    │   │   │                       │   ├── WalletDataListAdapter.kt
    │   │   │                       │   ├── WalletDataListItem.kt
    │   │   │                       │   └── WalletDataListViewHolder.kt
    │   │   │                       ├── networking/
    │   │   │                       │   └── interceptor/
    │   │   │                       │       └── AcceptLanguageHeaderInterceptor.kt
    │   │   │                       ├── onboarding/
    │   │   │                       │   ├── OnboardingActivity.kt
    │   │   │                       │   ├── OnboardingAgbFragment.kt
    │   │   │                       │   ├── OnboardingContentFragment.kt
    │   │   │                       │   ├── OnboardingIntroFragment.kt
    │   │   │                       │   ├── OnboardingPreInfoFragment.kt
    │   │   │                       │   ├── agbupdate/
    │   │   │                       │   │   └── UpdateboardingAgbFragment.kt
    │   │   │                       │   ├── certificatelight/
    │   │   │                       │   │   └── UpdateboardingCertificateLightFragment.kt
    │   │   │                       │   └── validity/
    │   │   │                       │       ├── UpdateboardingValidity1Fragment.kt
    │   │   │                       │       ├── UpdateboardingValidity2Fragment.kt
    │   │   │                       │       ├── UpdateboardingValidity3Fragment.kt
    │   │   │                       │       └── UpdateboardingValidity4Fragment.kt
    │   │   │                       ├── pdf/
    │   │   │                       │   ├── PdfViewModel.kt
    │   │   │                       │   ├── export/
    │   │   │                       │   │   ├── PdfExportFragment.kt
    │   │   │                       │   │   ├── PdfExportShareContract.kt
    │   │   │                       │   │   └── PdfExportState.kt
    │   │   │                       │   └── net/
    │   │   │                       │       ├── PdfExportRepository.kt
    │   │   │                       │       ├── PdfExportRequestBody.kt
    │   │   │                       │       ├── PdfExportResponse.kt
    │   │   │                       │       └── PdfExportService.kt
    │   │   │                       ├── qr/
    │   │   │                       │   ├── VerifierInfoDialogFragment.kt
    │   │   │                       │   └── WalletQrScanFragment.kt
    │   │   │                       ├── ratconversion/
    │   │   │                       │   └── RatConversionFragment.kt
    │   │   │                       ├── renewal/
    │   │   │                       │   ├── QrCodeRenewalErrorCodes.kt
    │   │   │                       │   ├── QrCodeRenewalFragment.kt
    │   │   │                       │   ├── QrCodeRenewalViewModel.kt
    │   │   │                       │   ├── model/
    │   │   │                       │   │   ├── QrCodeRenewalResponse.kt
    │   │   │                       │   │   └── QrCodeRenewalViewState.kt
    │   │   │                       │   └── net/
    │   │   │                       │       ├── QrCodeRenewalBody.kt
    │   │   │                       │       ├── QrCodeRenewalRepository.kt
    │   │   │                       │       └── QrCodeRenewalService.kt
    │   │   │                       ├── transfercode/
    │   │   │                       │   ├── TransferCodeCreationFragment.kt
    │   │   │                       │   ├── TransferCodeCreationViewModel.kt
    │   │   │                       │   ├── TransferCodeDetailFragment.kt
    │   │   │                       │   ├── TransferCodeErrorCodes.kt
    │   │   │                       │   ├── TransferCodeHowToFragment.kt
    │   │   │                       │   ├── TransferCodeIntroFragment.kt
    │   │   │                       │   ├── TransferCodeViewModel.kt
    │   │   │                       │   ├── logic/
    │   │   │                       │   │   ├── Luhn.kt
    │   │   │                       │   │   └── TransferCodeCrypto.kt
    │   │   │                       │   ├── model/
    │   │   │                       │   │   ├── ConvertedCertificate.kt
    │   │   │                       │   │   ├── TransferCodeConversionState.kt
    │   │   │                       │   │   ├── TransferCodeCreationResponse.kt
    │   │   │                       │   │   ├── TransferCodeCreationState.kt
    │   │   │                       │   │   └── TransferCodeModel.kt
    │   │   │                       │   ├── net/
    │   │   │                       │   │   ├── CovidCert.kt
    │   │   │                       │   │   ├── CovidCertDelivery.kt
    │   │   │                       │   │   ├── DeliveryRegistration.kt
    │   │   │                       │   │   ├── DeliveryRepository.kt
    │   │   │                       │   │   ├── DeliveryService.kt
    │   │   │                       │   │   └── RequestDeliveryPayload.kt
    │   │   │                       │   ├── view/
    │   │   │                       │   │   ├── TransferCodeBubbleView.kt
    │   │   │                       │   │   ├── TransferCodeView.kt
    │   │   │                       │   │   └── TransferCodeWaitingView.kt
    │   │   │                       │   └── worker/
    │   │   │                       │       └── TransferWorker.kt
    │   │   │                       ├── travel/
    │   │   │                       │   ├── ForeignValidityFragment.kt
    │   │   │                       │   ├── ForeignValidityViewModel.kt
    │   │   │                       │   └── ForeignValidityViewState.kt
    │   │   │                       ├── util/
    │   │   │                       │   ├── BitmapUtil.kt
    │   │   │                       │   ├── ModeValidityStateUtil.kt
    │   │   │                       │   ├── NotificationUtil.kt
    │   │   │                       │   ├── QrCode.kt
    │   │   │                       │   └── VerificationStateUtil.kt
    │   │   │                       └── vaccination/
    │   │   │                           ├── appointment/
    │   │   │                           │   └── VaccinationAppointmentFragment.kt
    │   │   │                           └── hint/
    │   │   │                               └── VaccinationHintViewModel.kt
    │   │   ├── play/
    │   │   │   ├── listings/
    │   │   │   │   ├── de-DE/
    │   │   │   │   │   ├── full-description.txt
    │   │   │   │   │   ├── short-description.txt
    │   │   │   │   │   └── title.txt
    │   │   │   │   ├── en-US/
    │   │   │   │   │   ├── full-description.txt
    │   │   │   │   │   ├── short-description.txt
    │   │   │   │   │   └── title.txt
    │   │   │   │   ├── fr-FR/
    │   │   │   │   │   ├── full-description.txt
    │   │   │   │   │   ├── short-description.txt
    │   │   │   │   │   └── title.txt
    │   │   │   │   └── it-IT/
    │   │   │   │       ├── full-description.txt
    │   │   │   │       ├── short-description.txt
    │   │   │   │       └── title.txt
    │   │   │   └── release-notes/
    │   │   │       └── en-US/
    │   │   │           └── default.txt
    │   │   └── res/
    │   │       ├── color/
    │   │       │   └── text_color_button.xml
    │   │       ├── drawable/
    │   │       │   ├── bg_add_certificate_option.xml
    │   │       │   ├── bg_border.xml
    │   │       │   ├── bg_bordered_button.xml
    │   │       │   ├── bg_bubble_bottom_left.xml
    │   │       │   ├── bg_certificate_bottom.xml
    │   │       │   ├── bg_certificate_bubble.xml
    │   │       │   ├── bg_certificate_bubble_bundesrot.xml
    │   │       │   ├── bg_certificate_bubble_ripple.xml
    │   │       │   ├── bg_certificate_detail_note.xml
    │   │       │   ├── bg_certificate_top.xml
    │   │       │   ├── bg_info_banner.xml
    │   │       │   ├── bg_type_bubble_small.xml
    │   │       │   ├── circle_white.xml
    │   │       │   ├── cutout_left.xml
    │   │       │   ├── cutout_right.xml
    │   │       │   ├── ic_add_certificate.xml
    │   │       │   ├── ic_arrow_right.xml
    │   │       │   ├── ic_calendar.xml
    │   │       │   ├── ic_certificate_light.xml
    │   │       │   ├── ic_check_mark.xml
    │   │       │   ├── ic_cloud.xml
    │   │       │   ├── ic_corner_offline.xml
    │   │       │   ├── ic_corner_process_error.xml
    │   │       │   ├── ic_covid_check_app.xml
    │   │       │   ├── ic_data_protection.xml
    │   │       │   ├── ic_drag.xml
    │   │       │   ├── ic_exchange.xml
    │   │       │   ├── ic_expire_1.xml
    │   │       │   ├── ic_expire_2.xml
    │   │       │   ├── ic_expire_3.xml
    │   │       │   ├── ic_expire_4.xml
    │   │       │   ├── ic_expire_5.xml
    │   │       │   ├── ic_expire_6.xml
    │   │       │   ├── ic_expire_7.xml
    │   │       │   ├── ic_faq_image.xml
    │   │       │   ├── ic_flag_ch.xml
    │   │       │   ├── ic_header_slim.xml
    │   │       │   ├── ic_launcher_background.xml
    │   │       │   ├── ic_launcher_foreground.xml
    │   │       │   ├── ic_list.xml
    │   │       │   ├── ic_online.xml
    │   │       │   ├── ic_pdf.xml
    │   │       │   ├── ic_pen_write.xml
    │   │       │   ├── ic_qr_certificate.xml
    │   │       │   ├── ic_qrcode.xml
    │   │       │   ├── ic_qrcode_add.xml
    │   │       │   ├── ic_qrcode_icon_placeholder.xml
    │   │       │   ├── ic_qrcode_scan.xml
    │   │       │   ├── ic_scan_code.xml
    │   │       │   ├── ic_transfer_code_list_failed.xml
    │   │       │   ├── ic_transfer_code_list_valid.xml
    │   │       │   ├── ic_transfer_notification.xml
    │   │       │   ├── ic_validation.xml
    │   │       │   ├── icon_ag.xml
    │   │       │   ├── icon_ai.xml
    │   │       │   ├── icon_ar.xml
    │   │       │   ├── icon_be.xml
    │   │       │   ├── icon_bl.xml
    │   │       │   ├── icon_bs.xml
    │   │       │   ├── icon_fr.xml
    │   │       │   ├── icon_ge.xml
    │   │       │   ├── icon_gl.xml
    │   │       │   ├── icon_gr.xml
    │   │       │   ├── icon_ju.xml
    │   │       │   ├── icon_lu.xml
    │   │       │   ├── icon_ne.xml
    │   │       │   ├── icon_nw.xml
    │   │       │   ├── icon_ow.xml
    │   │       │   ├── icon_sg.xml
    │   │       │   ├── icon_sh.xml
    │   │       │   ├── icon_so.xml
    │   │       │   ├── icon_sz.xml
    │   │       │   ├── icon_tg.xml
    │   │       │   ├── icon_ti.xml
    │   │       │   ├── icon_ur.xml
    │   │       │   ├── icon_vd.xml
    │   │       │   ├── icon_vs.xml
    │   │       │   ├── icon_zg.xml
    │   │       │   ├── icon_zh.xml
    │   │       │   ├── illu_add_certificate.xml
    │   │       │   ├── illu_faq_transfer_code.xml
    │   │       │   ├── illu_home_empty_state.xml
    │   │       │   ├── illu_how_it_works.xml
    │   │       │   ├── illu_how_to_scan.xml
    │   │       │   ├── illu_onboarding_covid_certificate.xml
    │   │       │   ├── illu_onboarding_hero.xml
    │   │       │   ├── illu_onboarding_privacy.xml
    │   │       │   ├── illu_transfer_code_failed.xml
    │   │       │   ├── illu_transfer_code_intro.xml
    │   │       │   ├── illu_transfer_code_waiting_phone.xml
    │   │       │   ├── illu_transfer_code_waiting_ripple.xml
    │   │       │   ├── illu_transfer_code_waiting_shadow.xml
    │   │       │   ├── illu_updateboarding_certificate_light.xml
    │   │       │   └── oval_horizontal.xml
    │   │       ├── drawable-v24/
    │   │       │   └── ic_launcher_foreground.xml
    │   │       ├── layout/
    │   │       │   ├── activity_main.xml
    │   │       │   ├── dialog_fragment_certificate_banner_info.xml
    │   │       │   ├── dialog_fragment_mode_info.xml
    │   │       │   ├── dialog_fragment_refresh_button_info.xml
    │   │       │   ├── fragment_certificate_add.xml
    │   │       │   ├── fragment_certificate_detail.xml
    │   │       │   ├── fragment_certificate_light_conversion.xml
    │   │       │   ├── fragment_certificate_light_detail.xml
    │   │       │   ├── fragment_certificate_light_pager.xml
    │   │       │   ├── fragment_certificate_pager.xml
    │   │       │   ├── fragment_certificates_list.xml
    │   │       │   ├── fragment_foreign_validity.xml
    │   │       │   ├── fragment_home.xml
    │   │       │   ├── fragment_how_to_scan.xml
    │   │       │   ├── fragment_onboarding_agb.xml
    │   │       │   ├── fragment_onboarding_content.xml
    │   │       │   ├── fragment_onboarding_intro.xml
    │   │       │   ├── fragment_onboarding_pre_info.xml
    │   │       │   ├── fragment_pdf_export.xml
    │   │       │   ├── fragment_qr_code_renewal.xml
    │   │       │   ├── fragment_qr_scan.xml
    │   │       │   ├── fragment_rat_conversion.xml
    │   │       │   ├── fragment_transfer_code_creation.xml
    │   │       │   ├── fragment_transfer_code_detail.xml
    │   │       │   ├── fragment_transfer_code_howto.xml
    │   │       │   ├── fragment_transfer_code_intro.xml
    │   │       │   ├── fragment_transfer_code_pager.xml
    │   │       │   ├── fragment_updateboarding_agb.xml
    │   │       │   ├── fragment_updateboarding_certificate_light.xml
    │   │       │   ├── fragment_updateboarding_validity_1.xml
    │   │       │   ├── fragment_updateboarding_validity_2.xml
    │   │       │   ├── fragment_updateboarding_validity_3.xml
    │   │       │   ├── fragment_updateboarding_validity_4.xml
    │   │       │   ├── fragment_vaccination_appointment.xml
    │   │       │   ├── item_certificate_list.xml
    │   │       │   ├── item_debug_certificate_list.xml
    │   │       │   ├── item_detail_divider.xml
    │   │       │   ├── item_detail_mode.xml
    │   │       │   ├── item_detail_mode_refresh.xml
    │   │       │   ├── item_detail_modes_list.xml
    │   │       │   ├── item_detail_title.xml
    │   │       │   ├── item_detail_value.xml
    │   │       │   ├── item_detail_value_without_label.xml
    │   │       │   ├── item_foreign_rules_check_hint.xml
    │   │       │   ├── item_header_not_empty.xml
    │   │       │   ├── item_icon_text_info.xml
    │   │       │   ├── item_mode_list_info.xml
    │   │       │   ├── item_transfer_code_list.xml
    │   │       │   ├── item_vaccination_appointment_canton.xml
    │   │       │   ├── partial_certificate_detail_banners.xml
    │   │       │   ├── partial_home_add_certificate_options.xml
    │   │       │   ├── view_transfer_code.xml
    │   │       │   ├── view_transfer_code_bubble.xml
    │   │       │   └── view_transfer_code_waiting.xml
    │   │       ├── mipmap-anydpi-v26/
    │   │       │   ├── ic_launcher.xml
    │   │       │   └── ic_launcher_round.xml
    │   │       └── xml/
    │   │           └── filepaths.xml
    │   ├── prod/
    │   │   └── java/
    │   │       └── ch/
    │   │           └── admin/
    │   │               └── bag/
    │   │                   └── covidcertificate/
    │   │                       └── wallet/
    │   │                           └── debug/
    │   │                               └── WalletDebugFragment.kt
    │   └── test/
    │       └── java/
    │           └── ch/
    │               └── admin/
    │                   └── bag/
    │                       └── covidcertificate/
    │                           └── wallet/
    │                               └── transfercode/
    │                                   ├── LuhnTest.kt
    │                                   └── LuhnTestWrongCodes.kt
    └── testKeystore

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/actions/gradle_docker/action.yml
================================================
name: 'GradleDocker'
description: 'Run gradle inside Docker image'
inputs:
  gradle-cmd:  # id of input
    description: 'gradleCmd to run'
    required: true
runs:
  using: 'docker'
  image: '../../../Dockerfile'
  entrypoint: '.github/actions/gradle_docker/main.sh'
  args:
    - ${{ inputs.gradle-cmd }}

================================================
FILE: .github/actions/gradle_docker/main.sh
================================================
#!/bin/sh

cd $GITHUB_WORKSPACE
gradle $1

================================================
FILE: .github/workflows/appcenter_verifier_abn.yml
================================================
name: Build Verifier ABN

on:
  push:
    branches:
      - main
      - 'release/**'
  pull_request:
    branches:
      - main
      - 'release/**'

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
      with:
        submodules: true
    - name: Build with Gradle
      uses: ./.github/actions/gradle_docker
      with:
        gradle-cmd: verifier:assembleAbnRelease -PkeystorePassword=${{secrets.KEYSTORE_PASSWORD}} -PkeyAliasPassword=${{secrets.KEY_ALIAS_PASSWORD}}
    - name: upload artefact to App Center
      uses: wzieba/AppCenter-Github-Action@8db6b765c4d7ce337bd783ea986f17ce0c9a9e85
      with:
        appName: ${{secrets.APPCENTER_ORGANIZATION}}/${{secrets.APPCENTER_VERIFIER_APP_ABN}}
        token: ${{secrets.APPCENTER_API_TOKEN}}
        group: public
        file: verifier/build/outputs/apk/abn/release/verifier-abn-release.apk


================================================
FILE: .github/workflows/appcenter_verifier_dev.yml
================================================
name: Build Verifier DEV

on:
  push:
    branches:
      - main
      - 'release/**'
  pull_request:
    branches:
      - main
      - 'release/**'

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true
      - name: Build with Gradle
        uses: ./.github/actions/gradle_docker
        with:
          gradle-cmd: verifier:assembleDevRelease -PkeystorePassword=${{secrets.KEYSTORE_PASSWORD}} -PkeyAliasPassword=${{secrets.KEY_ALIAS_PASSWORD}}
      - name: upload artefact to App Center
        uses: wzieba/AppCenter-Github-Action@8db6b765c4d7ce337bd783ea986f17ce0c9a9e85
        with:
          appName: ${{secrets.APPCENTER_ORGANIZATION}}/${{secrets.APPCENTER_VERIFIER_APP_DEV}}
          token: ${{secrets.APPCENTER_API_TOKEN}}
          group: public
          file: verifier/build/outputs/apk/dev/release/verifier-dev-release.apk


================================================
FILE: .github/workflows/appcenter_verifier_prod.yml
================================================
name: Build Verifier PROD

on:
  push:
    branches:
      - main
      - 'release/**'
  pull_request:
    branches:
      - main
      - 'release/**'

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true
      - name: Build with Gradle
        uses: ./.github/actions/gradle_docker
        with:
          gradle-cmd: verifier:assembleProdRelease -PkeystorePassword=${{secrets.KEYSTORE_PASSWORD}} -PkeyAliasPassword=${{secrets.KEY_ALIAS_PASSWORD}}
      - name: upload artefact to App Center
        uses: wzieba/AppCenter-Github-Action@8db6b765c4d7ce337bd783ea986f17ce0c9a9e85
        with:
          appName: ${{secrets.APPCENTER_ORGANIZATION}}/${{secrets.APPCENTER_VERIFIER_APP}}
          token: ${{secrets.APPCENTER_API_TOKEN}}
          group: public
          file: verifier/build/outputs/apk/prod/release/verifier-prod-release.apk
      - name: Upload APK
        uses: actions/upload-artifact@v1.0.0
        with:
          name: verifier.apk
          path: verifier/build/outputs/apk/prod/release/verifier-prod-release.apk


================================================
FILE: .github/workflows/appcenter_verifier_prodfdroid.yml
================================================
name: Build Verifier PRODFDROID

on:
  push:
    branches:
      - main
      - 'release/**'
  pull_request:
    branches:
      - main
      - 'release/**'

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true
      - name: Build with Gradle
        uses: ./.github/actions/gradle_docker
        with:
          gradle-cmd: verifier:assembleProdRelease -PkeystorePassword=${{secrets.KEYSTORE_PASSWORD}} -PkeyAliasPassword=${{secrets.KEY_ALIAS_PASSWORD}} -PminSdkVersion=24
      - name: upload artefact to App Center
        uses: wzieba/AppCenter-Github-Action@8db6b765c4d7ce337bd783ea986f17ce0c9a9e85
        with:
          appName: ${{secrets.APPCENTER_ORGANIZATION}}/${{secrets.APPCENTER_VERIFIER_APP}}
          token: ${{secrets.APPCENTER_API_TOKEN}}
          group: public
          file: verifier/build/outputs/apk/prod/release/verifier-prod-release.apk
      - name: Upload APK
        uses: actions/upload-artifact@v1.0.0
        with:
          name: verifier.apk
          path: verifier/build/outputs/apk/prod/release/verifier-prod-release.apk


================================================
FILE: .github/workflows/appcenter_wallet_abn.yml
================================================
name: Build Wallet ABN

on:
  push:
    branches:
      - main
      - 'release/**'
  pull_request:
    branches:
      - main
      - 'release/**'

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
      with:
        submodules: true
    - name: Build with Gradle
      uses: ./.github/actions/gradle_docker
      with:
        gradle-cmd: wallet:assembleAbnRelease -PkeystorePassword=${{secrets.KEYSTORE_PASSWORD}} -PkeyAliasPassword=${{secrets.KEY_ALIAS_PASSWORD}}
    - name: upload artefact to App Center
      uses: wzieba/AppCenter-Github-Action@8db6b765c4d7ce337bd783ea986f17ce0c9a9e85
      with:
        appName: ${{secrets.APPCENTER_ORGANIZATION}}/${{secrets.APPCENTER_WALLET_APP_ABN}}
        token: ${{secrets.APPCENTER_API_TOKEN}}
        group: public
        file: wallet/build/outputs/apk/abn/release/wallet-abn-release.apk


================================================
FILE: .github/workflows/appcenter_wallet_dev.yml
================================================
name: Build Wallet DEV

on:
  push:
    branches:
      - main
      - 'release/**'
  pull_request:
    branches:
      - main
      - 'release/**'

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true
      - name: Build with Gradle
        uses: ./.github/actions/gradle_docker
        with:
          gradle-cmd: wallet:assembleDevRelease -PkeystorePassword=${{secrets.KEYSTORE_PASSWORD}} -PkeyAliasPassword=${{secrets.KEY_ALIAS_PASSWORD}}
      - name: upload artefact to App Center
        uses: wzieba/AppCenter-Github-Action@8db6b765c4d7ce337bd783ea986f17ce0c9a9e85
        with:
          appName: ${{secrets.APPCENTER_ORGANIZATION}}/${{secrets.APPCENTER_WALLET_APP_DEV}}
          token: ${{secrets.APPCENTER_API_TOKEN}}
          group: public
          file: wallet/build/outputs/apk/dev/release/wallet-dev-release.apk


================================================
FILE: .github/workflows/appcenter_wallet_prod.yml
================================================
name: Build Wallet PROD

on:
  push:
    branches:
      - main
      - 'release/**'
  pull_request:
    branches:
      - main
      - 'release/**'

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true
      - name: Build with Gradle
        uses: ./.github/actions/gradle_docker
        with:
          gradle-cmd: wallet:assembleProdRelease -PkeystorePassword=${{secrets.KEYSTORE_PASSWORD}} -PkeyAliasPassword=${{secrets.KEY_ALIAS_PASSWORD}}
      - name: upload artefact to App Center
        uses: wzieba/AppCenter-Github-Action@8db6b765c4d7ce337bd783ea986f17ce0c9a9e85
        with:
          appName: ${{secrets.APPCENTER_ORGANIZATION}}/${{secrets.APPCENTER_WALLET_APP}}
          token: ${{secrets.APPCENTER_API_TOKEN}}
          group: public
          file: wallet/build/outputs/apk/prod/release/wallet-prod-release.apk
      - name: Upload APK
        uses: actions/upload-artifact@v1.0.0
        with:
          name: wallet.apk
          path: wallet/build/outputs/apk/prod/release/wallet-prod-release.apk


================================================
FILE: .github/workflows/appcenter_wallet_prodfdroid.yml
================================================
name: Build Wallet PRODFDROID

on:
  push:
    branches:
      - main
      - 'release/**'
  pull_request:
    branches:
      - main
      - 'release/**'

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true
      - name: Build with Gradle
        uses: ./.github/actions/gradle_docker
        with:
          gradle-cmd: wallet:assembleProdRelease -PkeystorePassword=${{secrets.KEYSTORE_PASSWORD}} -PkeyAliasPassword=${{secrets.KEY_ALIAS_PASSWORD}} -PminSdkVersion=24
      - name: upload artefact to App Center
        uses: wzieba/AppCenter-Github-Action@8db6b765c4d7ce337bd783ea986f17ce0c9a9e85
        with:
          appName: ${{secrets.APPCENTER_ORGANIZATION}}/${{secrets.APPCENTER_WALLET_APP}}
          token: ${{secrets.APPCENTER_API_TOKEN}}
          group: public
          file: wallet/build/outputs/apk/prod/release/wallet-prod-release.apk
      - name: Upload APK
        uses: actions/upload-artifact@v1.0.0
        with:
          name: wallet.apk
          path: wallet/build/outputs/apk/prod/release/wallet-prod-release.apk


================================================
FILE: .github/workflows/browserstack_wallet_abn.yml
================================================
name: Build Browserstack UI-Test Wallet

on:
  push:
    branches:
      - main
      - 'release/**'
  pull_request:
    branches:
      - main
      - 'release/**'

jobs:

  build-app-and-upload:

    runs-on: ubuntu-latest

    outputs:
      app-url: ${{ steps.upload-app.outputs.app-url }}

    steps:
    - uses: actions/checkout@v2
      with:
        submodules: true
    - name: Build with Gradle
      uses: ./.github/actions/gradle_docker
      with:
        gradle-cmd: wallet:assembleAbnRelease -PkeystorePassword=${{secrets.KEYSTORE_PASSWORD}} -PkeyAliasPassword=${{secrets.KEY_ALIAS_PASSWORD}}
    - name: upload artefact to Browserstack
      run: curl -u ${{ secrets.BROWSERSTACK_USERNAME }}:${{ secrets.BROWSERSTACK_ACCESSKEY }} -X Post "https://api-cloud.browserstack.com/app-automate/espresso/v2/app" -F "file=@wallet/build/outputs/apk/abn/release/wallet-abn-release.apk" >> appResponse.json
    - id: upload-app
      run: echo ::set-output name=app-url::$(jq -r '.app_url'  appResponse.json)

  build-test-suite-and-upload:

    runs-on: ubuntu-latest

    outputs:
      test-url: ${{ steps.upload-test-suite.outputs.test-url }}

    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true
      - name: Build with Gradle
        uses: ./.github/actions/gradle_docker
        with:
          gradle-cmd: wallet:assembleAbnDebugAndroidTest -PkeystorePassword=${{secrets.KEYSTORE_PASSWORD}} -PkeyAliasPassword=${{secrets.KEY_ALIAS_PASSWORD}}
      - name: upload artefact to Browserstack
        run: curl -u ${{ secrets.BROWSERSTACK_USERNAME }}:${{ secrets.BROWSERSTACK_ACCESSKEY }} -X Post "https://api-cloud.browserstack.com/app-automate/espresso/v2/test-suite" -F "file=@wallet/build/outputs/apk/androidTest/abn/debug/wallet-abn-debug-androidTest.apk" >> testSuiteResponse.json
      - id: upload-test-suite
        run: echo ::set-output name=test-url::$(jq -r '.test_suite_url'  testSuiteResponse.json)


  run-tests:
    runs-on: ubuntu-latest
    needs: [build-app-and-upload, build-test-suite-and-upload]

    steps:
      - name: run normal tests
        run: curl -u ${{ secrets.BROWSERSTACK_USERNAME }}:${{ secrets.BROWSERSTACK_ACCESSKEY }} -X Post "https://api-cloud.browserstack.com/app-automate/espresso/v2/build" -d '{"app":"${{ needs.build-app-and-upload.outputs.app-url }}", "testSuite":"${{ needs.build-test-suite-and-upload.outputs.test-url }}", "devices":["Samsung Galaxy S10e-9.0"] , "language":"de", "annotation":["ch.admin.bag.covidcertificate.common.browserstack.Normal"]  }' -H "Content-Type:application/json"
      - name: run airplane tests
        run: curl -u ${{ secrets.BROWSERSTACK_USERNAME }}:${{ secrets.BROWSERSTACK_ACCESSKEY }} -X Post "https://api-cloud.browserstack.com/app-automate/espresso/v2/build" -d '{"app":"${{ needs.build-app-and-upload.outputs.app-url }}", "testSuite":"${{ needs.build-test-suite-and-upload.outputs.test-url }}", "devices":["Samsung Galaxy S10e-9.0"] , "networkProfile":"airplane-mode", "annotation":["ch.admin.bag.covidcertificate.common.browserstack.AirplaneMode"] }' -H "Content-Type:application/json"
      - name: run bad network tests
        run: curl -u ${{ secrets.BROWSERSTACK_USERNAME }}:${{ secrets.BROWSERSTACK_ACCESSKEY }} -X Post "https://api-cloud.browserstack.com/app-automate/espresso/v2/build" -d '{"app":"${{ needs.build-app-and-upload.outputs.app-url }}", "testSuite":"${{ needs.build-test-suite-and-upload.outputs.test-url }}", "devices":["Samsung Galaxy S10e-9.0"] , "networkProfile":"2g-gprs-lossy",  "annotation":["ch.admin.bag.covidcertificate.common.browserstack.BadNetwork"] }' -H "Content-Type:application/json"
      - name: run onboarding test
        run: curl -u ${{ secrets.BROWSERSTACK_USERNAME }}:${{ secrets.BROWSERSTACK_ACCESSKEY }} -X Post "https://api-cloud.browserstack.com/app-automate/espresso/v2/build" -d '{"app":"${{ needs.build-app-and-upload.outputs.app-url }}", "testSuite":"${{ needs.build-test-suite-and-upload.outputs.test-url }}", "devices":["Samsung Galaxy S10e-9.0"] , "language":"de", "annotation":["ch.admin.bag.covidcertificate.common.browserstack.Onboarding"]  }' -H "Content-Type:application/json"
      - name: run onboarding test offline
        run: curl -u ${{ secrets.BROWSERSTACK_USERNAME }}:${{ secrets.BROWSERSTACK_ACCESSKEY }} -X Post "https://api-cloud.browserstack.com/app-automate/espresso/v2/build" -d '{"app":"${{ needs.build-app-and-upload.outputs.app-url }}", "testSuite":"${{ needs.build-test-suite-and-upload.outputs.test-url }}", "devices":["Samsung Galaxy S10e-9.0"] , "language":"de", "networkProfile":"airplane-mode", "annotation":["ch.admin.bag.covidcertificate.common.browserstack.Onboarding"]  }' -H "Content-Type:application/json"




================================================
FILE: .github/workflows/build.yml
================================================
name: Build

on:
  push:
    branches:
      - main
      - 'release/**'
  pull_request:
jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true
          fetch-depth: 0  # Shallow clones should be disabled for a better relevancy of analysis
      - name: Set up JDK 11
        uses: actions/setup-java@v1
        with:
          java-version: 11
      - name: Cache SonarCloud packages
        uses: actions/cache@v1
        with:
          path: ~/.sonar/cache
          key: ${{ runner.os }}-sonar
          restore-keys: ${{ runner.os }}-sonar
      - name: Cache Gradle packages
        uses: actions/cache@v1
        with:
          path: ~/.gradle/caches
          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
          restore-keys: ${{ runner.os }}-gradle
      - name: Build and analyze
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}  # Needed to get PR information, if any
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
        run: ./gradlew sonarqube


================================================
FILE: .github/workflows/gradle-wrapper-validation.yml
================================================
name: Validate Gradle Wrapper

on: [push, pull_request]

jobs:
  validation:
    name: Validation
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true
      - uses: gradle/wrapper-validation-action@84d7e182ae7c7a37f200c184f64038fb0e62dd7d


================================================
FILE: .gitignore
================================================
# Built application files
*.apk
*.aar
*.ap_
*.aab

# Files for the ART/Dalvik VM
*.dex

# Java class files
*.class

# Generated files
bin/
gen/
out/
#  Uncomment the following line in case you need and you don't have the release build type files in your app
# release/

# Gradle files
.gradle/
build/

# Local configuration file (sdk path, etc)
local.properties

# Proguard folder generated by Eclipse
proguard/

# Log Files
*.log

# Android Studio Navigation editor temp files
.navigation/

# Android Studio captures folder
captures/

# IntelliJ
*.iml
.idea/workspace.xml
.idea/tasks.xml
.idea/gradle.xml
.idea/assetWizardSettings.xml
.idea/dictionaries
.idea/libraries
# Android Studio 3 in .gitignore file.
.idea/caches
.idea/modules.xml
# Comment next line if keeping position of elements in Navigation Editor is relevant for you
.idea/navEditor.xml

# Keystore files
# Uncomment the following lines if you do not want to check your keystore files in.
#*.jks
#*.keystore

# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild
.cxx/

# Google Services (e.g. APIs or Firebase)
# google-services.json

# Freeline
freeline.py
freeline/
freeline_project_description.json

# fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md

# Version control
vcs.xml

# lint
lint/intermediates/
lint/generated/
lint/outputs/
lint/tmp/
# lint/reports/

.idea/misc.xml

.idea/

.DS_Store


================================================
FILE: Dockerfile
================================================
FROM gradle:7.2-jdk11

ENV ANDROID_SDK_URL https://dl.google.com/android/repository/commandlinetools-linux-7583922_latest.zip
ENV ANDROID_BUILD_TOOLS_VERSION 30.0.1
ENV ANDROID_HOME /usr/local/android-sdk-linux
ENV ANDROID_VERSION 30
ENV PATH ${PATH}:${ANDROID_HOME}/cmdline-tools/bin:${ANDROID_HOME}/platform-tools

RUN mkdir "$ANDROID_HOME" .android && \
    cd "$ANDROID_HOME" && \
    curl -o sdk.zip $ANDROID_SDK_URL && \
    unzip sdk.zip && \
    rm sdk.zip

RUN yes | ${ANDROID_HOME}/cmdline-tools/bin/sdkmanager --sdk_root=$ANDROID_HOME --licenses
RUN $ANDROID_HOME/cmdline-tools/bin/sdkmanager --sdk_root=$ANDROID_HOME --update
RUN $ANDROID_HOME/cmdline-tools/bin/sdkmanager --sdk_root=$ANDROID_HOME "build-tools;${ANDROID_BUILD_TOOLS_VERSION}" \
    "platforms;android-${ANDROID_VERSION}" \
    "platform-tools" 

RUN apt-get update
RUN apt-get install -y imagemagick
RUN convert -version


================================================
FILE: LICENSE
================================================
Mozilla Public License Version 2.0
==================================

1. Definitions
--------------

1.1. "Contributor"
    means each individual or legal entity that creates, contributes to
    the creation of, or owns Covered Software.

1.2. "Contributor Version"
    means the combination of the Contributions of others (if any) used
    by a Contributor and that particular Contributor's Contribution.

1.3. "Contribution"
    means Covered Software of a particular Contributor.

1.4. "Covered Software"
    means Source Code Form to which the initial Contributor has attached
    the notice in Exhibit A, the Executable Form of such Source Code
    Form, and Modifications of such Source Code Form, in each case
    including portions thereof.

1.5. "Incompatible With Secondary Licenses"
    means

    (a) that the initial Contributor has attached the notice described
        in Exhibit B to the Covered Software; or

    (b) that the Covered Software was made available under the terms of
        version 1.1 or earlier of the License, but not also under the
        terms of a Secondary License.

1.6. "Executable Form"
    means any form of the work other than Source Code Form.

1.7. "Larger Work"
    means a work that combines Covered Software with other material, in
    a separate file or files, that is not Covered Software.

1.8. "License"
    means this document.

1.9. "Licensable"
    means having the right to grant, to the maximum extent possible,
    whether at the time of the initial grant or subsequently, any and
    all of the rights conveyed by this License.

1.10. "Modifications"
    means any of the following:

    (a) any file in Source Code Form that results from an addition to,
        deletion from, or modification of the contents of Covered
        Software; or

    (b) any new file in Source Code Form that contains any Covered
        Software.

1.11. "Patent Claims" of a Contributor
    means any patent claim(s), including without limitation, method,
    process, and apparatus claims, in any patent Licensable by such
    Contributor that would be infringed, but for the grant of the
    License, by the making, using, selling, offering for sale, having
    made, import, or transfer of either its Contributions or its
    Contributor Version.

1.12. "Secondary License"
    means either the GNU General Public License, Version 2.0, the GNU
    Lesser General Public License, Version 2.1, the GNU Affero General
    Public License, Version 3.0, or any later versions of those
    licenses.

1.13. "Source Code Form"
    means the form of the work preferred for making modifications.

1.14. "You" (or "Your")
    means an individual or a legal entity exercising rights under this
    License. For legal entities, "You" includes any entity that
    controls, is controlled by, or is under common control with You. For
    purposes of this definition, "control" means (a) the power, direct
    or indirect, to cause the direction or management of such entity,
    whether by contract or otherwise, or (b) ownership of more than
    fifty percent (50%) of the outstanding shares or beneficial
    ownership of such entity.

2. License Grants and Conditions
--------------------------------

2.1. Grants

Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:

(a) under intellectual property rights (other than patent or trademark)
    Licensable by such Contributor to use, reproduce, make available,
    modify, display, perform, distribute, and otherwise exploit its
    Contributions, either on an unmodified basis, with Modifications, or
    as part of a Larger Work; and

(b) under Patent Claims of such Contributor to make, use, sell, offer
    for sale, have made, import, and otherwise transfer either its
    Contributions or its Contributor Version.

2.2. Effective Date

The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.

2.3. Limitations on Grant Scope

The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:

(a) for any code that a Contributor has removed from Covered Software;
    or

(b) for infringements caused by: (i) Your and any other third party's
    modifications of Covered Software, or (ii) the combination of its
    Contributions with other software (except as part of its Contributor
    Version); or

(c) under Patent Claims infringed by Covered Software in the absence of
    its Contributions.

This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).

2.4. Subsequent Licenses

No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).

2.5. Representation

Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.

2.6. Fair Use

This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.

2.7. Conditions

Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.

3. Responsibilities
-------------------

3.1. Distribution of Source Form

All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.

3.2. Distribution of Executable Form

If You distribute Covered Software in Executable Form then:

(a) such Covered Software must also be made available in Source Code
    Form, as described in Section 3.1, and You must inform recipients of
    the Executable Form how they can obtain a copy of such Source Code
    Form by reasonable means in a timely manner, at a charge no more
    than the cost of distribution to the recipient; and

(b) You may distribute such Executable Form under the terms of this
    License, or sublicense it under different terms, provided that the
    license for the Executable Form does not attempt to limit or alter
    the recipients' rights in the Source Code Form under this License.

3.3. Distribution of a Larger Work

You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).

3.4. Notices

You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.

3.5. Application of Additional Terms

You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.

4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------

If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.

5. Termination
--------------

5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.

5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.

5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.

************************************************************************
*                                                                      *
*  6. Disclaimer of Warranty                                           *
*  -------------------------                                           *
*                                                                      *
*  Covered Software is provided under this License on an "as is"       *
*  basis, without warranty of any kind, either expressed, implied, or  *
*  statutory, including, without limitation, warranties that the       *
*  Covered Software is free of defects, merchantable, fit for a        *
*  particular purpose or non-infringing. The entire risk as to the     *
*  quality and performance of the Covered Software is with You.        *
*  Should any Covered Software prove defective in any respect, You     *
*  (not any Contributor) assume the cost of any necessary servicing,   *
*  repair, or correction. This disclaimer of warranty constitutes an   *
*  essential part of this License. No use of any Covered Software is   *
*  authorized under this License except under this disclaimer.         *
*                                                                      *
************************************************************************

************************************************************************
*                                                                      *
*  7. Limitation of Liability                                          *
*  --------------------------                                          *
*                                                                      *
*  Under no circumstances and under no legal theory, whether tort      *
*  (including negligence), contract, or otherwise, shall any           *
*  Contributor, or anyone who distributes Covered Software as          *
*  permitted above, be liable to You for any direct, indirect,         *
*  special, incidental, or consequential damages of any character      *
*  including, without limitation, damages for lost profits, loss of    *
*  goodwill, work stoppage, computer failure or malfunction, or any    *
*  and all other commercial damages or losses, even if such party      *
*  shall have been informed of the possibility of such damages. This   *
*  limitation of liability shall not apply to liability for death or   *
*  personal injury resulting from such party's negligence to the       *
*  extent applicable law prohibits such limitation. Some               *
*  jurisdictions do not allow the exclusion or limitation of           *
*  incidental or consequential damages, so this exclusion and          *
*  limitation may not apply to You.                                    *
*                                                                      *
************************************************************************

8. Litigation
-------------

Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.

9. Miscellaneous
----------------

This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.

10. Versions of the License
---------------------------

10.1. New Versions

Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.

10.2. Effect of New Versions

You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.

10.3. Modified Versions

If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).

10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses

If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.

Exhibit A - Source Code Form License Notice
-------------------------------------------

  This Source Code Form is subject to the terms of the Mozilla Public
  License, v. 2.0. If a copy of the MPL was not distributed with this
  file, You can obtain one at http://mozilla.org/MPL/2.0/.

If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.

You may add additional accurate notices of copyright ownership.

Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------

  This Source Code Form is "Incompatible With Secondary Licenses", as
  defined by the Mozilla Public License, v. 2.0.


================================================
FILE: README.md
================================================
# COVID Certificate Apps - Android

[![License: MPL 2.0](https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg)](https://github.com/admin-ch/CovidCertificate-App-Android/blob/main/LICENSE)
![Android Build Wallet](https://github.com/admin-ch/CovidCertificate-App-Android/actions/workflows/appcenter_wallet_dev.yml/badge.svg)
![Android Build Verifier](https://github.com/admin-ch/CovidCertificate-App-Android/actions/workflows/appcenter_verifier_dev.yml/badge.svg)

This project is released by the the [Federal Office of Information Technology, Systems and Telecommunication FOITT](https://www.bit.admin.ch/)
on behalf of the [Federal Office of Public Health FOPH](https://www.bag.admin.ch/).
The app design, UX and implementation was done by [Ubique](https://www.ubique.ch?app=github).

## COVID Certificate App

COVID Certificate is the official app for storing and presenting COVID certificates issued in Switzerland.
The certificates are kept and checked locally on the user's phone.

<p align="verticalcenter">
<a href='https://play.google.com/store/apps/details?id=ch.admin.bag.covidcertificate.wallet'>
<img alt='Get it on Google Play' src='badges/googleplay.png' width="30%"/>
</a>
<a href='https://f-droid.org/packages/ch.admin.bag.covidcertificate.wallet'>
<img alt='Get it on F-Droid' src='badges/fdroid.png' width="30%"/>
</a>
<a href='https://appgallery.huawei.com/#/app/C104434571'>
<img alt='Explore it on AppGallery' src='badges/appgallery.png' width="30%"/>
</a>
</p>

<p align="center">
<img src="wallet/src/main/play/listings/en-US/graphics/phone-screenshots/EN_01.png" width="15%">
<img src="wallet/src/main/play/listings/en-US/graphics/phone-screenshots/EN_02.png" width="15%">
<img src="wallet/src/main/play/listings/en-US/graphics/phone-screenshots/EN_03.png" width="15%">
<img src="wallet/src/main/play/listings/en-US/graphics/phone-screenshots/EN_04.png" width="15%">
<img src="wallet/src/main/play/listings/en-US/graphics/phone-screenshots/EN_05.png" width="15%">
</p>

## COVID Certificate Check App

COVID Certificate Check is the official app for checking COVID certificates in Switzerland.
The validation is executed locally on the phone and no information of the scanned certificates is saved.

<p align="verticalcenter">
<a href='https://play.google.com/store/apps/details?id=ch.admin.bag.covidcertificate.verifier'>
<img alt='Get it on Google Play' src='badges/googleplay.png' width="30%"/>
</a>
<a href='https://f-droid.org/packages/ch.admin.bag.covidcertificate.verifier'>
<img alt='Get it on F-Droid' src='badges/fdroid.png' width="30%"/>
</a>
<a href='https://appgallery.huawei.com/#/app/C104435637'>
<img alt='Explore it on AppGallery' src='badges/appgallery.png' width="30%"/>
</a>
</p>

<p align="center">
<img src="verifier/src/main/play/listings/en-US/graphics/phone-screenshots/EN_01.png" width="20%">
<img src="verifier/src/main/play/listings/en-US/graphics/phone-screenshots/EN_02.png" width="20%">
<img src="verifier/src/main/play/listings/en-US/graphics/phone-screenshots/EN_03.png" width="20%">
</p>

## Contribution Guide

This project is truly open-source and we welcome any feedback on the code regarding both the implementation and security aspects.

Bugs or potential problems should be reported using Github issues.
We welcome all pull requests that improve the quality of the source code.
Please note that the app will be available with approved translations in English, German, French, Italian, Rumantsch.

## Repositories

* Android App: [CovidCertificate-App-Android](https://github.com/admin-ch/CovidCertificate-App-Android)
* Android SDK: [CovidCertificate-SDK-Android](https://github.com/admin-ch/CovidCertificate-SDK-Android)
* iOS App: [CovidCertificate-App-iOS](https://github.com/admin-ch/CovidCertificate-App-iOS)
* For all others, see the [Github organisation](https://github.com/admin-ch/)

## Installation and Building

The apps require at least Android 6 (Marshmallow).

To build the project you need at least Java 11 and Android Studio 2020.3.1.

You can also build the apps directly:
```sh
$ ./gradlew verifier:assembleProdRelease
$ ./gradlew wallet:assembleProdRelease
```
Note that in order for that to work, you must have set up your own keystore.

The APK is generated under `app/build/outputs/apk/prod/release/app-prod-release.apk` where `app` is one of: `verifier`, `wallet`.

## Reproducible builds

To verify that the app distributed on the Play Store was built by the source code published here, please see the instructions
in [REPRODUCIBLE_BUILDS.md](REPRODUCIBLE_BUILDS.md).

## License

This project is licensed under the terms of the MPL 2 license. See the [LICENSE](LICENSE) file for details.


================================================
FILE: REPRODUCIBLE_BUILDS.md
================================================
# Reproducible Builds

This document outlines how you can reproduce the Android app.

The instructions below are for the wallet app.
To reproduce the verifier app, change **all** occurences of `wallet` to `verifier`.

## Prerequisites

1. Make sure you have both [Docker](https://www.docker.com/) and `git` installed.
2. Clone the repository
3. Checkout the tag (or branch or commit) that corresponds to the version of your app (e.g., 1.0.0)

```shell
git clone https://github.com/admin-ch/CovidCertificate-App-Android.git ~/CovidCertificate-App-Android
cd ~/CovidCertificate-App-Android
git tag       # List all available tags
git checkout v2.7.0-2700-wallet
```

## Verifying the app

### Step 1: Check your app version and build timestamp

1. Open the app
2. Click on the `i` button in the top-right corner
3. Check the app version in the top right corner
4. Check the build timestamp in the bottom right corner, which is the number before the slash (e.g., 1622186583268), and record its value to be used later

### Step 2: Extract the APK from your device

1. Make sure you have `adb` installed
2. Connect your phone to your computer
3. Extract the APK from the phone:

```shell
adb pull `adb shell pm path ch.admin.bag.covidcertificate.wallet | cut -d':' -f2` wallet-store.apk
```

If you want to check the version of the APK you are pulling from your device:

```shell
adb shell dumpsys package ch.admin.bag.covidcertificate.wallet | grep versionName=| cut -d '=' -f 2
```

### Step 3: Reproduce it

TLDR: Run the script and follow its instructions:

```shell
./buildAndCompare.sh wallet-store.apk
```

The script will do the following:

1. Build a Docker image with the required Android tools
2. (Optionally) Generate a dummy key store for signing
3. Build the app from source in the Docker container
4. Compare the APK pulled from your phone with the APK built from source

To manually compare to files you can run:

```shell
python3 apkdiff.py wallet-built.apk wallet-store.apk
```



================================================
FILE: apkdiff.py
================================================

# Taken from https://github.com/DrKLO/Telegram/blob/master/apkdiff.py on June 4th, 2020

import sys
from zipfile import ZipFile

def compareFiles(first, second):
	while True:
		firstBytes = first.read(4096);
		secondBytes = second.read(4096);
		if firstBytes != secondBytes:
			return False

		if firstBytes == b"":
			break

	return True

def compare(first, second):
	FILES_TO_IGNORE = ["META-INF/MANIFEST.MF", "META-INF/CERT.RSA", "META-INF/CERT.SF"]

	firstZip = ZipFile(first, 'r')
	secondZip = ZipFile(second, 'r')

	firstList = list(filter(lambda firstInfo: firstInfo.filename not in FILES_TO_IGNORE, firstZip.infolist()))
	secondList = list(filter(lambda secondInfo: secondInfo.filename not in FILES_TO_IGNORE, secondZip.infolist()))

	apksAreTheSame = True

	if len(firstList) != len(secondList):
	    print("APKs has different amount of files (%d != %d)" % (len(firstList), len(secondList)))
	    apksAreTheSame = False

	for firstInfo in firstList:
		found = False
		for secondInfo in secondList:
			if firstInfo.filename == secondInfo.filename:
				found = True
				firstFile = firstZip.open(firstInfo, 'r')
				secondFile = secondZip.open(secondInfo, 'r')

				if compareFiles(firstFile, secondFile) != True:
					print("APK file %s does not match" % firstInfo.filename)
					apksAreTheSame = False

				secondList.remove(secondInfo)
				break

		if found == False:
			print("file %s not found in second APK" % firstInfo.filename)
			apksAreTheSame = False

	if len(secondList) != 0:
		for secondInfo in secondList:
			print("file %s not found in first APK" % secondInfo.filename)
		apksAreTheSame = False

	return apksAreTheSame

if __name__ == '__main__':
	if len(sys.argv) != 3:
		print("Usage: apkdiff <pathToFirstApk> <pathToSecondApk>")
		sys.exit(1)

	if sys.argv[1] == sys.argv[2] or compare(sys.argv[1], sys.argv[2]) == True:
		print("APKs are the same!")
	else:
		print("APKs are different!")


================================================
FILE: build.gradle
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
	ext.kotlin_version = "1.6.10"
	repositories {
		google()
		mavenCentral()
		maven {
			url "https://plugins.gradle.org/m2/"
		}
	}
	dependencies {
		classpath 'com.android.tools:r8:3.0.73'
		classpath 'com.android.tools.build:gradle:7.0.4'
		classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
		classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
		classpath 'ch.ubique.gradle:ubdiag-android:7.0.2'
	}
}

allprojects {
	repositories {
		google()
		mavenCentral()
	}
}

task clean(type: Delete) {
	delete rootProject.buildDir
}

================================================
FILE: buildAndCompare.sh
================================================
#!/bin/bash

# Script to automate the building and comparing of the CovidCertificate apps
#
# The first and only argument should be the path to the APK to be compared.

set -eu

if [[ $# -ne 1 ]]; then
  echo "Pass the path/to/store.apk as an argument!"
  exit 1
fi
referenceApk=$1

echo "Which app would you like to build ('wallet' or 'verifier')?"
read appName

echo "Do you want to provide a keystore [Yn]?"
read willProvideKeystore

case "$willProvideKeystore" in
  # Case 1: Autogenerate a dummy keystore
  [nN][oO]|[nN])
  echo "[WARNING] Auto-generating a dummy keystore with default credentials. Do NOT use the resulting APK!"
  rm -f "$appName"/insecure.keystore
  # Generate a keystore with default credentials that is only valid 1 day
  keytool -genkeypair -storepass password -keypass password -alias keyAlias -keyalg RSA -keystore "$appName"/insecure.keystore -dname 'CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown' -validity 1
  keystoreFile="$appName"/insecure.keystore
  keystorePassword=password
  keyAlias=keyAlias
  keyAliasPassword=password
  ;;

  # Case 2: Let the user choose a keystore
  *)
  echo "Please enter the keystore filename (e.g. wallet/build.keystore):"
  read keystoreFile

  echo "Please enter the keystore password:"
  read -s keystorePassword

  echo "Please enter the keyAlias:"
  read keyAlias

  echo "Please enter the keyAlias password:"
  read -s keyAliasPassword
  ;;
esac

echo "Please enter the build timestamp (e.g. 1622186583268):"
read buildTimestamp

# This is necessary because Ubique's gradle plugin will automatically set the branch.
# Here we want to override it in order to reproduce the build.
echo "Please enter the branch off which the release was build (e.g. release/version-1.0.0):"
read buildBranch

echo "Please enter the git tag (e.g. v2.7.0-2700-wallet) or branch (e.g. release/version-1.0.0) to be reproduced."
echo "This is what will be checked out and reproduced."
read tree

echo "Do you want to build the F-Droid version [yN]?"
read fdroid

# Set gradle task to be run
case "$fdroid" in
  [yY][eE][sS]|[yY])
  overrideMinSdk="-PminSdkVersion=24"
  ;;

  *)
  overrideMinSdk=""
  ;;
esac

echo "Building apk from source..."

# Clean up any existing images
docker images -a | grep "covidcertificate-builder" | awk '{print $3}' | xargs -r docker rmi

# Build a fresh container image
docker build -t covidcertificate-builder .

# Prepare the build command (for readability)
currentPath=`pwd`
buildCommand=$(cat <<EOF
git clone https://github.com/admin-ch/CovidCertificate-App-Android.git;
cd CovidCertificate-App-Android;
git checkout $tree;
gradle $appName:assembleProdRelease -PkeystorePassword='$keystorePassword' -PkeyAlias=$keyAlias -PkeyAliasPassword='$keyAliasPassword' -PkeystoreFile=/home/covidcertificate/external/$keystoreFile -PbuildTimestamp=$buildTimestamp -Pbranch=$buildBranch $overrideMinSdk;
cp $appName/build/outputs/apk/prod/release/$appName-prod-release.apk /home/covidcertificate/external/$appName-built.apk
EOF
)
buildCommand=$(echo -n "$buildCommand" | tr '\n' ' ' ) # replace newlines by spaces

# Build the app in the container
docker run --rm -v "$currentPath":/home/covidcertificate/external -w /home/covidcertificate covidcertificate-builder /bin/bash -c -eux "$buildCommand"

# Remove dummy keystore again
rm -f "$appName"/insecure.keystore

echo "Comparing the APK built from source with the reference APK..."
python3 apkdiff.py $appName-built.apk $referenceApk



================================================
FILE: common/.gitignore
================================================
/build

================================================
FILE: common/build.gradle
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

plugins {
	id 'com.android.library'
	id 'kotlin-android'
	id 'com.google.devtools.ksp' version '1.6.10-1.0.4'
}

ext.readPropertyWithDefault = { paramName, defaultValue ->
	if (project.hasProperty(paramName)) {
		return project.getProperties().get(paramName)
	} else {
		Properties properties = new Properties()
		if (project.rootProject.file('local.properties').exists()) {
			properties.load(project.rootProject.file('local.properties').newDataInputStream())
		}
		if (properties.getProperty(paramName) != null) {
			return properties.getProperty(paramName)
		} else {
			return defaultValue
		}
	}
}

android {
	compileSdkVersion 31

	defaultConfig {
		minSdkVersion readPropertyWithDefault('minSdkVersion', '23').toInteger()
		targetSdkVersion 31

		// Stops the Gradle plugin’s automatic rasterization of vectors
		generatedDensities = []

		testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
		consumerProguardFiles "consumer-rules.pro"
	}

	productFlavors {
		dev {}
		abn {}
		prod {}
	}

	flavorDimensions "version"

	buildTypes {
		release {
			minifyEnabled false
			proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
		}
	}

	compileOptions {
		coreLibraryDesugaringEnabled true

		sourceCompatibility JavaVersion.VERSION_1_8
		targetCompatibility JavaVersion.VERSION_1_8
	}

	kotlinOptions {
		jvmTarget = '1.8'
	}

	buildFeatures {
		viewBinding true
	}
}

dependencies {
	coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'

	api 'ch.admin.bag.covidcertificate:sdk-android:2.3.3'

	implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
	implementation 'androidx.core:core-ktx:1.7.0'
	implementation 'androidx.appcompat:appcompat:1.4.1'
	api 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.1'
	implementation 'androidx.fragment:fragment-ktx:1.4.1'
	implementation 'com.google.android.material:material:1.5.0'
	implementation 'androidx.security:security-crypto:1.0.0'
	ksp 'com.squareup.moshi:moshi-kotlin-codegen:1.13.0'

	// ZXing base QR code scanner
	api 'ch.ubique.android:qrscanner-zxing:1.0.0-dev-6'

	api 'com.augustcellars.cose:cose-java:1.1.0'
	api 'org.bouncycastle:bcprov-jdk15on:1.69'

	androidTestImplementation 'androidx.test.ext:junit:1.1.3'
	androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}


================================================
FILE: common/consumer-rules.pro
================================================


================================================
FILE: common/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

================================================
FILE: common/src/abn/java/ch/admin/bag/covidcertificate/common/debug/DebugFragment.kt
================================================
package ch.admin.bag.covidcertificate.common.debug
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

import android.content.Context
import androidx.fragment.app.Fragment

open class DebugFragment : Fragment() {

	companion object {
		fun newInstance(): DebugFragment = DebugFragment()

		const val EXISTS = false

		fun initDebug(context: Context) {}
	}

}

================================================
FILE: common/src/dev/java/ch/admin/bag/covidcertificate/common/debug/DebugFragment.kt
================================================
package ch.admin.bag.covidcertificate.common.debug
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import ch.admin.bag.covidcertificate.common.databinding.FragmentDebugBinding
import ch.admin.bag.covidcertificate.sdk.android.net.CertificatePinning

open class DebugFragment : Fragment() {

	companion object {
		fun newInstance(): DebugFragment = DebugFragment()

		const val EXISTS = true

		fun initDebug(context: Context) {
			CertificatePinning.enabled = DebugSecureStorage.getInstance(context).isCertPinningEnabled
		}
	}

	private var _binding: FragmentDebugBinding? = null
	protected val binding get() = _binding!!

	private lateinit var debugSecureStorage: DebugSecureStorage

	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		debugSecureStorage = DebugSecureStorage.getInstance(requireContext())
	}

	override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
		_binding = FragmentDebugBinding.inflate(inflater, container, false)
		return binding.root
	}

	override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
		binding.toolbar.setNavigationOnClickListener {
			parentFragmentManager.popBackStack()
		}

		binding.buttonToggleCertificatePinning.apply {
			isChecked = debugSecureStorage.isCertPinningEnabled

			setOnCheckedChangeListener { _, isChecked ->
				debugSecureStorage.isCertPinningEnabled = isChecked
				CertificatePinning.enabled = isChecked
			}
		}
	}

	override fun onDestroyView() {
		super.onDestroyView()
		_binding = null
	}
}

================================================
FILE: common/src/dev/java/ch/admin/bag/covidcertificate/common/debug/DebugSecureStorage.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.debug

import android.content.Context
import ch.admin.bag.covidcertificate.sdk.android.net.CertificatePinning
import ch.admin.bag.covidcertificate.sdk.android.utils.EncryptedSharedPreferencesUtil
import ch.admin.bag.covidcertificate.sdk.android.utils.SingletonHolder

class DebugSecureStorage private constructor(context: Context) {

	companion object : SingletonHolder<DebugSecureStorage, Context>(::DebugSecureStorage) {
		private const val PREFERENCES = "DebugSecureStorage"
		private const val KEY_CERT_PINNING_ENABLED = "KEY_CERT_PINNING_ENABLED"
	}

	private val prefs = EncryptedSharedPreferencesUtil.initializeSharedPreferences(context, PREFERENCES)

	var isCertPinningEnabled: Boolean
		get() = prefs.getBoolean(KEY_CERT_PINNING_ENABLED, CertificatePinning.enabled)
		set(value) = prefs.edit().putBoolean(KEY_CERT_PINNING_ENABLED, value).apply()

}

================================================
FILE: common/src/dev/res/xml/network_security_config.xml
================================================
<?xml version="1.0" encoding="utf-8"?><!--
  ~ Copyright (c) 2020 Ubique Innovation AG <https://www.ubique.ch>
  ~
  ~ This Source Code Form is subject to the terms of the Mozilla Public
  ~ License, v. 2.0. If a copy of the MPL was not distributed with this
  ~ file, You can obtain one at https://mozilla.org/MPL/2.0/.
  ~
  ~ SPDX-License-Identifier: MPL-2.0
  -->

<network-security-config>
	<base-config cleartextTrafficPermitted="true">
		<trust-anchors>
			<certificates src="system" />
			<!-- Trust user added CAs in dev app only -->
			<certificates src="user" />
		</trust-anchors>
	</base-config>
</network-security-config>

================================================
FILE: common/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
  ~
  ~ This Source Code Form is subject to the terms of the Mozilla Public
  ~ License, v. 2.0. If a copy of the MPL was not distributed with this
  ~ file, You can obtain one at https://mozilla.org/MPL/2.0/.
  ~
  ~ SPDX-License-Identifier: MPL-2.0
  -->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
	package="ch.admin.bag.covidcertificate.common">

</manifest>

================================================
FILE: common/src/main/assets/impressum/de/impressum.html
================================================
<!--
  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
  ~
  ~ This Source Code Form is subject to the terms of the Mozilla Public
  ~ License, v. 2.0. If a copy of the MPL was not distributed with this
  ~ file, You can obtain one at https://mozilla.org/MPL/2.0/.
  ~
  ~ SPDX-License-Identifier: MPL-2.0
  -->

<!DOCTYPE html>
<html lang="de"><head>
    <title>  </title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    
    
    <link rel="stylesheet" href="../scss/main.min.css">
</head><body>
<header>
    <div class="title">{APP_NAME}</div>
    <div class="version">Version {VERSION}</div>
</header>
<div class="container impressum">

    <h1>Herausgeber</h1>

    <picture>
        <img src="../img/bundeslogo-bag.svg" class="bag-logo" alt="Bundesamt für Gesundheit BAG">
    </picture>
  
    <h2>Weitere Informationen</h2>
    <a class="link" href="https://www.bag.admin.ch/bag/de/home/krankheiten/ausbrueche-epidemien-pandemien/aktuelle-ausbrueche-epidemien/novel-cov/covid-zertifikat.html">
        <img src="../img/ic-link-external.svg" alt="">
        www.bag.admin.ch
    </a>

    <h2>Infoline Coronavirus</h2>
    <a class="link" href="tel:&#43;41584630000">
        <img src="../img/ic-call.svg" alt="">
        &#43;41 58 463 00 00
    </a>

    <h2>Rechtliches</h2>
    <a class="link" href="{LAW_LINK}">
        <img src="../img/ic-link-external.svg" alt="">
        Datenschutzerklärung &amp; Nutzungsbedingungen
    </a>

    <div class="divider"></div>

    <h1>Umsetzung &amp; Betrieb</h1>
    
    <picture>
        <img src="../img/bundeslogo-bit.svg" class="bag-logo" alt="Bundesamt für Informatik und Telekommunikation BIT">
    </picture>

    <h2>Technische Hilfe</h2>
    <a class="link" href="tel:&#43;41584660799">
        <img src="../img/ic-call.svg" alt="">
        &#43;41 58 466 07 99
    </a>
   
    <div class="divider"></div>

    <h1>In Zusammenarbeit mit</h1>
    <picture>
        <img src="../img/logo-ubique.svg" class="logo logo-ubique" alt="">
    </picture>
    <a class="link" href="https://www.ubique.ch/?app={PARAM_APP_IDENTIFIER}">
        <img src="../img/ic-link-external.svg" alt="">
        www.ubique.ch
    </a>

    <div class="divider"></div>

    <h1>Quellcode</h1>
    <p class="text">Der Quellcode des Covid Certificate Systems (inkl. dieser App) ist Open-Source und kann auf GitHub eingesehen werden.</p>
    <a class="link" href="https://www.github.com/admin-ch">
        <img src="../img/ic-link-external.svg" alt="">
        www.github.com/admin-ch
    </a>

    <div class="divider"></div>

    <a href="ccert://licence.html" class="licence-link">
        <h1>Lizenzen</h1>
        <picture>
            <img src="../img/ic-arrow.svg" alt="">
        </picture>
    </a>
</div>
<footer>
    <div class="build">{BUILD}</div>
</footer>
</body>
</html>

================================================
FILE: common/src/main/assets/impressum/de/licence.html
================================================
<!--
  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
  ~
  ~ This Source Code Form is subject to the terms of the Mozilla Public
  ~ License, v. 2.0. If a copy of the MPL was not distributed with this
  ~ file, You can obtain one at https://mozilla.org/MPL/2.0/.
  ~
  ~ SPDX-License-Identifier: MPL-2.0
  -->

<!DOCTYPE html>
<html lang="de"><head>
    <title>  </title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    
    
    <link rel="stylesheet" href="../scss/main.min.css">
</head><body>
<div class="container licence">
    <h1>Lizenzen</h1>
    <div class="list1">
    <ul>
<li>This app uses <strong>COVID Certificate Android SDK</strong> licensed under the <strong>MPL 2</strong> license</li>
<li>This app uses <strong>androidx</strong>, <strong>kotlinx</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Material Components For Android</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>ZXing</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Retrofit</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Moshi</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Jackson</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Gson</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>hcert-kotlin</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>dgc-java</strong> licensed under the <strong>MIT license</strong> license</li>
<li>This app uses <strong>COSE-JAVA</strong> licensed under the <strong>BSD-3-Clause</strong> license</li>
<li>This app uses <strong>Java JWT</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Bouncy Castle</strong> licensed under the <strong>MIT</strong> license</li>
<li>This app uses <strong>Fira Code Font</strong> licensed under the <strong>OFL-1.1</strong> license</li>
</ul>
    </div>
    <div class="licence-list">
    <ul>
<li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 license</a></li>
<li><a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause license</a></li>
<li><a href="https://opensource.org/licenses/MIT">MIT license</a></li>
<li><a href="https://opensource.org/licenses/MPL-2.0">MPL 2 license</a></li>
<li><a href="https://opensource.org/licenses/OFL-1.1">SIL OPEN FONT LICENSE</a></li>
</ul>
    </div>
</div>
</body>
</html>

================================================
FILE: common/src/main/assets/impressum/en/impressum.html
================================================
<!--
  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
  ~
  ~ This Source Code Form is subject to the terms of the Mozilla Public
  ~ License, v. 2.0. If a copy of the MPL was not distributed with this
  ~ file, You can obtain one at https://mozilla.org/MPL/2.0/.
  ~
  ~ SPDX-License-Identifier: MPL-2.0
  -->

<!DOCTYPE html>
<html lang="en"><head>
    <title>  </title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    
    
    <link rel="stylesheet" href="../scss/main.min.css">
</head><body>
<header>
    <div class="title">{APP_NAME}</div>
    <div class="version">Version {VERSION}</div>
</header>
<div class="container impressum">

    <h1>Published by</h1>

    <picture>
        <img src="../img/bundeslogo-bag.svg" class="bag-logo" alt="Federal Office of Public Health FOPH">
    </picture>
  
    <h2>Further information</h2>
    <a class="link" href="https://www.bag.admin.ch/bag/en/home/krankheiten/ausbrueche-epidemien-pandemien/aktuelle-ausbrueche-epidemien/novel-cov/covid-zertifikat.html">
        <img src="../img/ic-link-external.svg" alt="">
        www.bag.admin.ch
    </a>

    <h2>Infoline Coronavirus</h2>
    <a class="link" href="tel:&#43;41584630000">
        <img src="../img/ic-call.svg" alt="">
        &#43;41 58 463 00 00
    </a>

    <h2>Legal</h2>
    <a class="link" href="{LAW_LINK}">
        <img src="../img/ic-link-external.svg" alt="">
        Data Protection Statement &amp; Conditions of Use
    </a>

    <div class="divider"></div>

    <h1>Development &amp; operation</h1>
    
    <picture>
        <img src="../img/bundeslogo-bit.svg" class="bag-logo" alt="Federal Office of Information Technology, Systems and Telecommunication FOITT">
    </picture>

    <h2>Technical support</h2>
    <a class="link" href="tel:&#43;41584660799">
        <img src="../img/ic-call.svg" alt="">
        &#43;41 58 466 07 99
    </a>
   
    <div class="divider"></div>

    <h1>In collaboration with</h1>
    <picture>
        <img src="../img/logo-ubique.svg" class="logo logo-ubique" alt="">
    </picture>
    <a class="link" href="https://www.ubique.ch/?app={PARAM_APP_IDENTIFIER}">
        <img src="../img/ic-link-external.svg" alt="">
        www.ubique.ch
    </a>

    <div class="divider"></div>

    <h1>Source code</h1>
    <p class="text">The source code of the COVID Certificate System (including this app) is open source and can be viewed on GitHub.</p>
    <a class="link" href="https://www.github.com/admin-ch">
        <img src="../img/ic-link-external.svg" alt="">
        www.github.com/admin-ch
    </a>

    <div class="divider"></div>

    <a href="ccert://licence.html" class="licence-link">
        <h1>Licences</h1>
        <picture>
            <img src="../img/ic-arrow.svg" alt="">
        </picture>
    </a>
</div>
<footer>
    <div class="build">{BUILD}</div>
</footer>
</body>
</html>

================================================
FILE: common/src/main/assets/impressum/en/licence.html
================================================
<!--
  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
  ~
  ~ This Source Code Form is subject to the terms of the Mozilla Public
  ~ License, v. 2.0. If a copy of the MPL was not distributed with this
  ~ file, You can obtain one at https://mozilla.org/MPL/2.0/.
  ~
  ~ SPDX-License-Identifier: MPL-2.0
  -->

<!DOCTYPE html>
<html lang="en"><head>
    <title>  </title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    
    
    <link rel="stylesheet" href="../scss/main.min.css">
</head><body>
<div class="container licence">
    <h1>Licences</h1>
    <div class="list1">
    <ul>
<li>This app uses <strong>COVID Certificate Android SDK</strong> licensed under the <strong>MPL 2</strong> license</li>
<li>This app uses <strong>androidx</strong>, <strong>kotlinx</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Material Components For Android</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>ZXing</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Retrofit</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Moshi</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Jackson</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Gson</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>hcert-kotlin</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>dgc-java</strong> licensed under the <strong>MIT license</strong> license</li>
<li>This app uses <strong>COSE-JAVA</strong> licensed under the <strong>BSD-3-Clause</strong> license</li>
<li>This app uses <strong>Java JWT</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Bouncy Castle</strong> licensed under the <strong>MIT</strong> license</li>
<li>This app uses <strong>Fira Code Font</strong> licensed under the <strong>OFL-1.1</strong> license</li>
</ul>
    </div>
    <div class="licence-list">
    <ul>
<li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 license</a></li>
<li><a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause license</a></li>
<li><a href="https://opensource.org/licenses/MIT">MIT license</a></li>
<li><a href="https://opensource.org/licenses/MPL-2.0">MPL 2 license</a></li>
<li><a href="https://opensource.org/licenses/OFL-1.1">SIL OPEN FONT LICENSE</a></li>
</ul>
    </div>
</div>
</body>
</html>

================================================
FILE: common/src/main/assets/impressum/fr/impressum.html
================================================
<!--
  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
  ~
  ~ This Source Code Form is subject to the terms of the Mozilla Public
  ~ License, v. 2.0. If a copy of the MPL was not distributed with this
  ~ file, You can obtain one at https://mozilla.org/MPL/2.0/.
  ~
  ~ SPDX-License-Identifier: MPL-2.0
  -->

<!DOCTYPE html>
<html lang="fr"><head>
    <title>  </title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    
    
    <link rel="stylesheet" href="../scss/main.min.css">
</head><body>
<header>
    <div class="title">{APP_NAME}</div>
    <div class="version">Version {VERSION}</div>
</header>
<div class="container impressum">

    <h1>Éditeur</h1>

    <picture>
        <img src="../img/bundeslogo-bag.svg" class="bag-logo" alt="Office fédéral de la santé publique OFSP">
    </picture>
  
    <h2>Informations complémentaires</h2>
    <a class="link" href="https://www.bag.admin.ch/bag/fr/home/krankheiten/ausbrueche-epidemien-pandemien/aktuelle-ausbrueche-epidemien/novel-cov/covid-zertifikat.html">
        <img src="../img/ic-link-external.svg" alt="">
        www.bag.admin.ch
    </a>

    <h2>Infoline Coronavirus</h2>
    <a class="link" href="tel:&#43;41584630000">
        <img src="../img/ic-call.svg" alt="">
        &#43;41 58 463 00 00
    </a>

    <h2>Indications légales</h2>
    <a class="link" href="{LAW_LINK}">
        <img src="../img/ic-link-external.svg" alt="">
        Déclaration de confidentialité &amp; condition d&#39;utilisation
    </a>

    <div class="divider"></div>

    <h1>Mise en application &amp; opération</h1>
    
    <picture>
        <img src="../img/bundeslogo-bit.svg" class="bag-logo" alt="Office fédéral de l&#39;informatique et de la télécommunication OFIT">
    </picture>

    <h2>Assistance technique</h2>
    <a class="link" href="tel:&#43;41584660799">
        <img src="../img/ic-call.svg" alt="">
        &#43;41 58 466 07 99
    </a>
   
    <div class="divider"></div>

    <h1>En collaboration avec</h1>
    <picture>
        <img src="../img/logo-ubique.svg" class="logo logo-ubique" alt="">
    </picture>
    <a class="link" href="https://www.ubique.ch/?app={PARAM_APP_IDENTIFIER}">
        <img src="../img/ic-link-external.svg" alt="">
        www.ubique.ch
    </a>

    <div class="divider"></div>

    <h1>Code source</h1>
    <p class="text">Le code source du système de Certificat COVID (y compris cette application) est open source et peut être trouvé sur GitHub.</p>
    <a class="link" href="https://www.github.com/admin-ch">
        <img src="../img/ic-link-external.svg" alt="">
        www.github.com/admin-ch
    </a>

    <div class="divider"></div>

    <a href="ccert://licence.html" class="licence-link">
        <h1>Licences</h1>
        <picture>
            <img src="../img/ic-arrow.svg" alt="">
        </picture>
    </a>
</div>
<footer>
    <div class="build">{BUILD}</div>
</footer>
</body>
</html>

================================================
FILE: common/src/main/assets/impressum/fr/licence.html
================================================
<!--
  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
  ~
  ~ This Source Code Form is subject to the terms of the Mozilla Public
  ~ License, v. 2.0. If a copy of the MPL was not distributed with this
  ~ file, You can obtain one at https://mozilla.org/MPL/2.0/.
  ~
  ~ SPDX-License-Identifier: MPL-2.0
  -->

<!DOCTYPE html>
<html lang="fr"><head>
    <title>  </title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    
    
    <link rel="stylesheet" href="../scss/main.min.css">
</head><body>
<div class="container licence">
    <h1>Licences</h1>
    <div class="list1">
    <ul>
<li>This app uses <strong>COVID Certificate Android SDK</strong> licensed under the <strong>MPL 2</strong> license</li>
<li>This app uses <strong>androidx</strong>, <strong>kotlinx</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Material Components For Android</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>ZXing</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Retrofit</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Moshi</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Jackson</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Gson</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>hcert-kotlin</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>dgc-java</strong> licensed under the <strong>MIT license</strong> license</li>
<li>This app uses <strong>COSE-JAVA</strong> licensed under the <strong>BSD-3-Clause</strong> license</li>
<li>This app uses <strong>Java JWT</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Bouncy Castle</strong> licensed under the <strong>MIT</strong> license</li>
<li>This app uses <strong>Fira Code Font</strong> licensed under the <strong>OFL-1.1</strong> license</li>
</ul>
    </div>
    <div class="licence-list">
    <ul>
<li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 license</a></li>
<li><a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause license</a></li>
<li><a href="https://opensource.org/licenses/MIT">MIT license</a></li>
<li><a href="https://opensource.org/licenses/MPL-2.0">MPL 2 license</a></li>
<li><a href="https://opensource.org/licenses/OFL-1.1">SIL OPEN FONT LICENSE</a></li>
</ul>
    </div>
</div>
</body>
</html>

================================================
FILE: common/src/main/assets/impressum/it/impressum.html
================================================
<!--
  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
  ~
  ~ This Source Code Form is subject to the terms of the Mozilla Public
  ~ License, v. 2.0. If a copy of the MPL was not distributed with this
  ~ file, You can obtain one at https://mozilla.org/MPL/2.0/.
  ~
  ~ SPDX-License-Identifier: MPL-2.0
  -->

<!DOCTYPE html>
<html lang="it"><head>
    <title>  </title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    
    
    <link rel="stylesheet" href="../scss/main.min.css">
</head><body>
<header>
    <div class="title">{APP_NAME}</div>
    <div class="version">Version {VERSION}</div>
</header>
<div class="container impressum">

    <h1>Editore</h1>

    <picture>
        <img src="../img/bundeslogo-bag.svg" class="bag-logo" alt="Ufficio federale della sanità pubblica UFSP">
    </picture>
  
    <h2>Ulteriori informazioni</h2>
    <a class="link" href="https://www.bag.admin.ch/bag/it/home/krankheiten/ausbrueche-epidemien-pandemien/aktuelle-ausbrueche-epidemien/novel-cov/covid-zertifikat.html">
        <img src="../img/ic-link-external.svg" alt="">
        www.bag.admin.ch
    </a>

    <h2>Infoline Coronavirus</h2>
    <a class="link" href="tel:&#43;41584630000">
        <img src="../img/ic-call.svg" alt="">
        &#43;41 58 463 00 00
    </a>

    <h2>Note legali</h2>
    <a class="link" href="{LAW_LINK}">
        <img src="../img/ic-link-external.svg" alt="">
        Informativa sulla protezione dei dati &amp; condizioni d&#39;uso
    </a>

    <div class="divider"></div>

    <h1>Realizzazione &amp; operazione</h1>
    
    <picture>
        <img src="../img/bundeslogo-bit.svg" class="bag-logo" alt="Ufficio federale dell&#39;informatica e della telecomunicazione UFIT">
    </picture>

    <h2>Supporto tecnico</h2>
    <a class="link" href="tel:&#43;41584660799">
        <img src="../img/ic-call.svg" alt="">
        &#43;41 58 466 07 99
    </a>
   
    <div class="divider"></div>

    <h1>In collaborazione con</h1>
    <picture>
        <img src="../img/logo-ubique.svg" class="logo logo-ubique" alt="">
    </picture>
    <a class="link" href="https://www.ubique.ch/?app={PARAM_APP_IDENTIFIER}">
        <img src="../img/ic-link-external.svg" alt="">
        www.ubique.ch
    </a>

    <div class="divider"></div>

    <h1>Codice sorgente</h1>
    <p class="text">Il codice sorgente del Covid Certificate System (compresa questa applicazione) è open source e può essere trovato su GitHub.</p>
    <a class="link" href="https://www.github.com/admin-ch">
        <img src="../img/ic-link-external.svg" alt="">
        www.github.com/admin-ch
    </a>

    <div class="divider"></div>

    <a href="ccert://licence.html" class="licence-link">
        <h1>Licenze</h1>
        <picture>
            <img src="../img/ic-arrow.svg" alt="">
        </picture>
    </a>
</div>
<footer>
    <div class="build">{BUILD}</div>
</footer>
</body>
</html>

================================================
FILE: common/src/main/assets/impressum/it/licence.html
================================================
<!--
  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
  ~
  ~ This Source Code Form is subject to the terms of the Mozilla Public
  ~ License, v. 2.0. If a copy of the MPL was not distributed with this
  ~ file, You can obtain one at https://mozilla.org/MPL/2.0/.
  ~
  ~ SPDX-License-Identifier: MPL-2.0
  -->

<!DOCTYPE html>
<html lang="it"><head>
    <title>  </title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    
    
    <link rel="stylesheet" href="../scss/main.min.css">
</head><body>
<div class="container licence">
    <h1>Licenze</h1>
    <div class="list1">
    <ul>
<li>This app uses <strong>COVID Certificate Android SDK</strong> licensed under the <strong>MPL 2</strong> license</li>
<li>This app uses <strong>androidx</strong>, <strong>kotlinx</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Material Components For Android</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>ZXing</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Retrofit</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Moshi</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Jackson</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Gson</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>hcert-kotlin</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>dgc-java</strong> licensed under the <strong>MIT license</strong> license</li>
<li>This app uses <strong>COSE-JAVA</strong> licensed under the <strong>BSD-3-Clause</strong> license</li>
<li>This app uses <strong>Java JWT</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Bouncy Castle</strong> licensed under the <strong>MIT</strong> license</li>
<li>This app uses <strong>Fira Code Font</strong> licensed under the <strong>OFL-1.1</strong> license</li>
</ul>
    </div>
    <div class="licence-list">
    <ul>
<li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 license</a></li>
<li><a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause license</a></li>
<li><a href="https://opensource.org/licenses/MIT">MIT license</a></li>
<li><a href="https://opensource.org/licenses/MPL-2.0">MPL 2 license</a></li>
<li><a href="https://opensource.org/licenses/OFL-1.1">SIL OPEN FONT LICENSE</a></li>
</ul>
    </div>
</div>
</body>
</html>

================================================
FILE: common/src/main/assets/impressum/rm/impressum.html
================================================
<!--
  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
  ~
  ~ This Source Code Form is subject to the terms of the Mozilla Public
  ~ License, v. 2.0. If a copy of the MPL was not distributed with this
  ~ file, You can obtain one at https://mozilla.org/MPL/2.0/.
  ~
  ~ SPDX-License-Identifier: MPL-2.0
  -->

<!DOCTYPE html>
<html lang="rm"><head>
    <title>  </title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    
    
    <link rel="stylesheet" href="../scss/main.min.css">
</head><body>
<header>
    <div class="title">{APP_NAME}</div>
    <div class="version">Version {VERSION}</div>
</header>
<div class="container impressum">

    <h1>Editur</h1>

    <picture>
        <img src="../img/bundeslogo-bag.svg" class="bag-logo" alt="Uffizi federal da sanadad publica UFSP">
    </picture>
  
    <h2>Ulteriuras infurmaziuns</h2>
    <a class="link" href="https://www.bag.admin.ch/bag/de/home/krankheiten/ausbrueche-epidemien-pandemien/aktuelle-ausbrueche-epidemien/novel-cov/covid-zertifikat.html">
        <img src="../img/ic-link-external.svg" alt="">
        www.bag.admin.ch
    </a>

    <h2>Infoline Coronavirus</h2>
    <a class="link" href="tel:&#43;41584630000">
        <img src="../img/ic-call.svg" alt="">
        &#43;41 58 463 00 00
    </a>

    <h2>Indicaziuns giuridicas</h2>
    <a class="link" href="{LAW_LINK}">
        <img src="../img/ic-link-external.svg" alt="">
        Basas legalas
    </a>

    <div class="divider"></div>

    <h1>Realisaziun &amp; gestiun</h1>
    
    <picture>
        <img src="../img/bundeslogo-bit.svg" class="bag-logo" alt="Uffizi federal d&#39;informatica e da telecommunicaziun UFIT">
    </picture>

    <h2>Agid tecnic</h2>
    <a class="link" href="tel:&#43;41584660799">
        <img src="../img/ic-call.svg" alt="">
        &#43;41 58 466 07 99
    </a>
   
    <div class="divider"></div>

    <h1>En collavuraziun cun</h1>
    <picture>
        <img src="../img/logo-ubique.svg" class="logo logo-ubique" alt="">
    </picture>
    <a class="link" href="https://www.ubique.ch/?app={PARAM_APP_IDENTIFIER}">
        <img src="../img/ic-link-external.svg" alt="">
        www.ubique.ch
    </a>

    <div class="divider"></div>

    <h1>Code da funtauna</h1>
    <p class="text">Il code da funtauna dal COVID Certificate System (incl. questa app) è open source e po vegnir consultà/chattà sin GitHub.</p>
    <a class="link" href="https://www.github.com/admin-ch">
        <img src="../img/ic-link-external.svg" alt="">
        www.github.com/admin-ch
    </a>

    <div class="divider"></div>

    <a href="ccert://licence.html" class="licence-link">
        <h1>Licenzas</h1>
        <picture>
            <img src="../img/ic-arrow.svg" alt="">
        </picture>
    </a>
</div>
<footer>
    <div class="build">{BUILD}</div>
</footer>
</body>
</html>

================================================
FILE: common/src/main/assets/impressum/rm/licence.html
================================================
<!--
  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
  ~
  ~ This Source Code Form is subject to the terms of the Mozilla Public
  ~ License, v. 2.0. If a copy of the MPL was not distributed with this
  ~ file, You can obtain one at https://mozilla.org/MPL/2.0/.
  ~
  ~ SPDX-License-Identifier: MPL-2.0
  -->

<!DOCTYPE html>
<html lang="rm"><head>
    <title>  </title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    
    
    <link rel="stylesheet" href="../scss/main.min.css">
</head><body>
<div class="container licence">
    <h1>Licenzas</h1>
    <div class="list1">
    <ul>
<li>This app uses <strong>COVID Certificate Android SDK</strong> licensed under the <strong>MPL 2</strong> license</li>
<li>This app uses <strong>androidx</strong>, <strong>kotlinx</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Material Components For Android</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>ZXing</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Retrofit</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Moshi</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Jackson</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Gson</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>hcert-kotlin</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>dgc-java</strong> licensed under the <strong>MIT license</strong> license</li>
<li>This app uses <strong>COSE-JAVA</strong> licensed under the <strong>BSD-3-Clause</strong> license</li>
<li>This app uses <strong>Java JWT</strong> licensed under the <strong>Apache 2.0</strong> license</li>
<li>This app uses <strong>Bouncy Castle</strong> licensed under the <strong>MIT</strong> license</li>
<li>This app uses <strong>Fira Code Font</strong> licensed under the <strong>OFL-1.1</strong> license</li>
</ul>
    </div>
    <div class="licence-list">
    <ul>
<li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 license</a></li>
<li><a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause license</a></li>
<li><a href="https://opensource.org/licenses/MIT">MIT license</a></li>
<li><a href="https://opensource.org/licenses/MPL-2.0">MPL 2 license</a></li>
<li><a href="https://opensource.org/licenses/OFL-1.1">SIL OPEN FONT LICENSE</a></li>
</ul>
    </div>
</div>
</body>
</html>

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/BaseActivity.kt
================================================
package ch.admin.bag.covidcertificate.common

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import ch.admin.bag.covidcertificate.common.data.ConfigSecureStorage
import ch.admin.bag.covidcertificate.common.util.LocaleUtil

open class BaseActivity : AppCompatActivity() {

	override fun attachBaseContext(newBase: Context) {
		val language = ConfigSecureStorage.getInstance(newBase).getUserLanguage()
		super.attachBaseContext(LocaleUtil.updateLanguage(newBase, language))
	}

}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/browserstack/AirplaneMode.kt
================================================
/*
 * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.browserstack

annotation class AirplaneMode


================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/browserstack/BadNetwork.kt
================================================
/*
 * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.browserstack

annotation class BadNetwork


================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/browserstack/Normal.kt
================================================
/*
 * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.browserstack

annotation class Normal


================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/browserstack/Onboarding.kt
================================================
/*
 * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.browserstack

annotation class Onboarding


================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/config/CertificateRenewalInfoDetailModel.kt
================================================
/*
 * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.config

import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = true)
data class CertificateRenewalInfoDetailModel(
	val iconAndroid: String,
	val text: String
)

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/config/CertificateRenewalInfoModel.kt
================================================
/*
 * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.config

import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = true)
data class CertificateRenewalInfoModel(
	val heading: String,
	val infos: List<CertificateRenewalInfoDetailModel>,
	val faqLinkText: String,
	val faqLinkUrl: String,
)

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/config/CertificateRenewalType.kt
================================================
/*
 * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.config

import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = false)
enum class CertificateRenewalType {
	INFO, EXPIRED, RENEWED
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/config/CheckModesInfosModel.kt
================================================
package ch.admin.bag.covidcertificate.common.config

import com.squareup.moshi.JsonClass

//for verifier
@JsonClass(generateAdapter = true)
data class CheckModesInfosModel(
	val infos: Map<String, CheckModeInfoModel>?,
	val unselected: VerifierInfos?
)

@JsonClass(generateAdapter = true)
data class VerifierInfos(
	val infos: List<VerifierInfoDetails>?
)

@JsonClass(generateAdapter = true)
data class VerifierInfoDetails(
	val iconAndroid: String,
	val iconIos: String,
	val text: String
)

//for wallet
@JsonClass(generateAdapter = true)
data class CheckModesInfoModel(
	val title: String?,
	val modes: Map<String, WalletModeModel>?,
)


@JsonClass(generateAdapter = true)
data class WalletModeModel(
	val ok: WalletModeDetails,
	val notOk: WalletModeDetails
)

@JsonClass(generateAdapter = true)
data class WalletModeDetails(
	val iconAndroid: String,
	val iconIos: String,
	val text: String
)

@JsonClass(generateAdapter = true)
data class CheckModeInfoModel(
	val title: String,
	val hexColor: String,
	val infos: List<CheckModeInfoEntry>
)

data class CheckModeInfoModelWithId(
	val id: String,
	val title: String,
	val hexColor: String,
	val infos: List<CheckModeInfoEntry>
)

@JsonClass(generateAdapter = true)
data class CheckModeInfoEntry(
	val iconAndroid: String,
	val text: String
)

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/config/ConfigModel.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.config

import ch.admin.bag.covidcertificate.common.faq.model.Faq
import ch.admin.bag.covidcertificate.common.faq.model.Header
import ch.admin.bag.covidcertificate.common.faq.model.Question
import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = true)
data class ConfigModel(
	val forceUpdate: Boolean,
	val infoBox: Map<String, InfoBoxModel>?,
	val questions: Map<String, FaqModel>?,
	val works: Map<String, FaqModel>?,
	val transferQuestions: Map<String, FaqModel>?,
	val transferWorks: Map<String, FaqModel>?,
	val androidTransferCheckIntervalMs: Long?,
	val androidTransferCheckBackoffMs: Long?,
	val lightCertificateActive: Boolean?,
	val pdfGenerationActive: Boolean?,
	val vaccinationHints: Map<String, List<VaccinationHintModel>>?,
	val vaccinationBookingInfo: Map<String, VaccinationBookingInfoModel>?,
	val showVaccinationHintHomescreen: Boolean?,
	val showVaccinationHintDetail: Boolean?,
	val showVaccinationHintTransfer: Boolean?,
	val timeshiftDetectionEnabled: Boolean?,
	val checkModesInfos: Map<String, CheckModesInfosModel>?,
	val checkModesInfo: Map<String, CheckModesInfoModel>?,
	val checkModeReselectAfterHours: Int?,
	val lightCertDurationInHours: Int?,
	val refreshButtonDisabled: Boolean?,
	val refreshButtonInfo: Map<String, RefreshButtonInfoModel>?,
	val eolBannerInfo: Map<String, Map<String, EolBannerInfoModel>>?,
	val foreignRulesCheckEnabled: Boolean?,
	val foreignRulesLinkText: Map<String, String>?,
	val foreignRulesLinkUrl: Map<String, String>?,
	val foreignRulesHints: Map<String, List<ForeignRulesHintModel>>?,
	val showRatConversionForm: Boolean?,
	val ratConversionFormUrl: String?,
	val certRenewalInfo: Map<String, Map<CertificateRenewalType, CertificateRenewalInfoModel>>?,
	val showValidityState: Boolean?,
	val covidCertificateNewsText: Map<String, String>?,
	val infoCovidCertificateNews: Map<String, InfoCovidCertificateNews>?,
) {
	fun getInfoBox(languageKey: String?): InfoBoxModel? = infoBox?.get(languageKey)
	fun getQuestionsFaqs(languageKey: String): FaqModel? = questions?.get(languageKey)
	fun getWorksFaqs(languageKey: String): FaqModel? = works?.get(languageKey)
	fun getTransferQuestionsFaqs(languageKey: String): FaqModel? = transferQuestions?.get(languageKey)
	fun getTransferWorksFaqs(languageKey: String): FaqModel? = transferWorks?.get(languageKey)
	fun getVaccinationHints(languageKey: String): List<VaccinationHintModel>? = vaccinationHints?.get(languageKey)
	fun getCheckModesInfos(languageKey: String): Map<String, CheckModeInfoModel>? = checkModesInfos?.get(languageKey)?.infos
	fun getUnselectedModesInfos(languageKey: String): VerifierInfos? = checkModesInfos?.get(languageKey)?.unselected
	fun getRefreshButtonInfo(languageKey: String): RefreshButtonInfoModel? = refreshButtonInfo?.get(languageKey)
	fun getEolBannerInfo(languageKey: String): Map<String, EolBannerInfoModel>? = eolBannerInfo?.get(languageKey)
	fun getForeignRulesLinkText(languageKey: String): String? = foreignRulesLinkText?.get(languageKey)
	fun getForeignRulesLinkUrl(languageKey: String): String? = foreignRulesLinkUrl?.get(languageKey)
	fun getForeignRulesHints(languageKey: String): List<ForeignRulesHintModel>? = foreignRulesHints?.get(languageKey)
	fun getCertRenewalInfo(languageKey: String): Map<CertificateRenewalType, CertificateRenewalInfoModel>? =
		certRenewalInfo?.get(languageKey)

	fun getCheckModes(languageKey: String): Map<String, WalletModeModel>? = checkModesInfo?.get(languageKey)?.modes
	fun getInfoModeTitle(languageKey: String): String? = checkModesInfo?.get(languageKey)?.title

	fun getVaccinationBookingInfo(languageKey: String): VaccinationBookingInfoModel? = vaccinationBookingInfo?.get(languageKey)

	fun getCovidCertificateNewsText(languageKey: String): String? = covidCertificateNewsText?.get(languageKey)

	fun getInfoCovidCertificateNews(languageKey: String): InfoCovidCertificateNews? = infoCovidCertificateNews?.get(languageKey)

	fun generateFaqItems(languageKey: String): List<Faq> {
		val itemsList = mutableListOf<Faq>()
		getQuestionsFaqs(languageKey)?.let { questionModel ->
			val questionItems = questionModel.faqEntries
			itemsList.add(Header(questionModel.faqIconAndroid, questionModel.faqTitle, questionModel.faqSubTitle))
			questionItems?.let {
				itemsList.addAll(it.map { faqEntry ->
					Question(
						faqEntry.title,
						faqEntry.text,
						linkTitle = faqEntry.linkTitle,
						linkUrl = faqEntry.linkUrl
					)
				})
			}
		}
		getWorksFaqs(languageKey)?.let { worksModel ->
			val questionItems = worksModel.faqEntries
			itemsList.add(Header(worksModel.faqIconAndroid, worksModel.faqTitle, worksModel.faqSubTitle))
			questionItems?.let {
				itemsList.addAll(it.map { faqEntry ->
					Question(
						faqEntry.title,
						faqEntry.text,
						linkTitle = faqEntry.linkTitle,
						linkUrl = faqEntry.linkUrl
					)
				})
			}
		}
		return itemsList
	}
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/config/ConfigViewModel.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.config

import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import ch.admin.bag.covidcertificate.common.config.ConfigModel
import ch.admin.bag.covidcertificate.common.net.ConfigRepository
import ch.admin.bag.covidcertificate.common.net.ConfigSpec
import kotlinx.coroutines.launch

abstract class ConfigViewModel(application: Application) : AndroidViewModel(application) {

	private val configMutableLiveData = MutableLiveData<ConfigModel>(ConfigRepository.getCurrentConfig(application))
	val configLiveData: LiveData<ConfigModel> = configMutableLiveData

	fun loadConfig(baseUrl: String, versionName: String, buildTime: String) {
		val configSpec = ConfigSpec(getApplication(), baseUrl, versionName, buildTime)
		val configRepository = ConfigRepository.getInstance(configSpec)

		viewModelScope.launch {
			configRepository.loadConfig(getApplication())?.let { config ->
				configMutableLiveData.postValue(config) }
		}
	}

}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/config/CovidCertificateNewsItem.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.config

import com.squareup.moshi.JsonClass
import java.io.Serializable

@JsonClass(generateAdapter = true)
data class CovidCertificateNewsItem(
	val iconAndroid: String?,
	val text: String?,
) : Serializable


================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/config/EolBannerInfoModel.kt
================================================
package ch.admin.bag.covidcertificate.common.config

import com.squareup.moshi.JsonClass
import java.io.Serializable

@JsonClass(generateAdapter = true)
data class EolBannerInfoModel(
	val homescreenHexColor: String,
	val homescreenTitle: String,
	val detailHexColor: String,
	val detailTitle: String,
	val detailText: String?,
	val detailMoreInfo: String,
	val popupTitle: String,
	val popupText1: String?,
	val popupBoldText: String?,
	val popupText2: String?,
	val popupLinkText: String,
	val popupLinkUrl: String,
) : Serializable


================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/config/FaqEntryModel.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.config

import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = true)
data class FaqEntryModel(
	val title: String,
	val text: String,
	val iconAndroid: String?,
	val linkTitle: String?,
	val linkUrl: String?
)

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/config/FaqIntroSection.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.config

import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = true)
data class FaqIntroSection(
	val iconAndroid: String,
	val text: String
)


================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/config/FaqModel.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.config

import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = true)
data class FaqModel(
	val faqTitle: String,
	val faqSubTitle: String?,
	val faqIntroSections: List<FaqIntroSection>?,
	val faqIconAndroid: String?,
	val faqEntries: List<FaqEntryModel>?
)

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/config/ForeignRulesHintModel.kt
================================================
/*
 * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.config

import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = true)
data class ForeignRulesHintModel(
	val iconAndroid: String,
	val text: String,
)

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/config/InfoBoxModel.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.config

import android.os.Parcel
import android.os.Parcelable
import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = true)
data class InfoBoxModel(
	val title: String,
	val msg: String,
	val url: String?,
	val urlTitle: String?,
	val isDismissible: Boolean,
	val infoId: Long
) : Parcelable {

	constructor(parcel: Parcel) : this(
		parcel.readString() ?: throw IllegalArgumentException("No title specified for InfoDialog"),
		parcel.readString() ?: throw IllegalArgumentException("No message specified for InfoDialog"),
		parcel.readString(),
		parcel.readString(),
		parcel.readByte() != 0.toByte(),
		parcel.readLong()
	) {
	}

	override fun writeToParcel(parcel: Parcel, flags: Int) {
		parcel.writeString(title)
		parcel.writeString(msg)
		parcel.writeString(url)
		parcel.writeString(urlTitle)
		parcel.writeByte(if (isDismissible) 1 else 0)
		parcel.writeLong(infoId)
	}

	override fun describeContents(): Int {
		return 0
	}

	companion object CREATOR : Parcelable.Creator<InfoBoxModel> {
		override fun createFromParcel(parcel: Parcel): InfoBoxModel {
			return InfoBoxModel(parcel)
		}

		override fun newArray(size: Int): Array<InfoBoxModel?> {
			return arrayOfNulls(size)
		}
	}
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/config/InfoCovidCertificateNews.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.config

import com.squareup.moshi.JsonClass
import java.io.Serializable

@JsonClass(generateAdapter = true)
data class InfoCovidCertificateNews(
	val title: String?,
	val newsItems: List<CovidCertificateNewsItem>,
) : Serializable

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/config/RefreshButtonInfoModel.kt
================================================
/*
 * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.config

import com.squareup.moshi.JsonClass
import java.io.Serializable

@JsonClass(generateAdapter = true)
data class RefreshButtonInfoModel(
	val title: String,
	val text1: String,
	val text2: String,
	val fatTitle: String,
	val text3: String,
	val linkText: String,
	val linkUrl: String,
) : Serializable

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/config/VaccinationBookingInfoModel.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.config

import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = true)
data class VaccinationBookingInfoModel(
	val title: String,
	val text: String,
	val info: String,
	val impfcheckTitle: String?,
	val impfcheckText: String?,
	val impfcheckButton: String?,
	val impfcheckUrl: String?
)


================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/config/VaccinationHintModel.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.config

import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = true)
data class VaccinationHintModel(
	val title: String,
	val text: String,
)


================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/data/ConfigSecureStorage.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.data

import android.content.Context
import androidx.core.content.edit
import ch.admin.bag.covidcertificate.common.config.ConfigModel
import ch.admin.bag.covidcertificate.sdk.android.utils.EncryptedSharedPreferencesUtil
import ch.admin.bag.covidcertificate.sdk.android.utils.SingletonHolder
import com.squareup.moshi.Moshi

class ConfigSecureStorage private constructor(context: Context) {

	companion object : SingletonHolder<ConfigSecureStorage, Context>(::ConfigSecureStorage) {
		private const val PREFERENCES = "ConfigSecureStorage"

		private const val KEY_CONFIG = "ConfigKey"
		private const val KEY_CONFIG_LAST_SUCCESS = "LastSuccessTimestampKey"
		private const val KEY_CONFIG_LAST_SUCCESS_APP_AND_OS_VERSION = "LastSuccessVersionKey"
		private const val KEY_CONFIG_SHOWN_INFO_BOX_ID = "LastShownInfoBoxId"

		private const val KEY_USER_LANGUAGE = "UserLanguage"

		private const val KEY_ZOOM_ACTIVE = "KEY_ZOOM_ACTIVE"

		private const val KEY_REFRESH_BUTTON_DISABLED_TIMESTAMP = "KEY_REFRESH_BUTTON_DISABLED_TIMESTAMP"

		private val moshi = Moshi.Builder().build()
		private val configModelAdapter = moshi.adapter(ConfigModel::class.java)
	}

	private val prefs = EncryptedSharedPreferencesUtil.initializeSharedPreferences(context, PREFERENCES)

	fun updateConfigData(config: ConfigModel, timestamp: Long, appVersion: String) {
		val editor = prefs.edit()
		editor.putLong(KEY_CONFIG_LAST_SUCCESS, timestamp)
		editor.putString(KEY_CONFIG_LAST_SUCCESS_APP_AND_OS_VERSION, appVersion)
		editor.putString(KEY_CONFIG, configModelAdapter.toJson(config))
		editor.apply()
	}

	fun getConfig(): ConfigModel? =
		prefs.getString(KEY_CONFIG, null)
			?.let { configModelAdapter.fromJson(it) }

	fun getConfigLastSuccessTimestamp(): Long =
		prefs.getLong(KEY_CONFIG_LAST_SUCCESS, 0)

	fun getConfigLastSuccessAppAndOSVersion(): String? =
		prefs.getString(KEY_CONFIG_LAST_SUCCESS_APP_AND_OS_VERSION, null)

	fun setLastShownInfoBoxId(infoBoxId: Long) = prefs.edit().putLong(KEY_CONFIG_SHOWN_INFO_BOX_ID, infoBoxId).apply()

	fun getLastShownInfoBoxId(): Long = prefs.getLong(KEY_CONFIG_SHOWN_INFO_BOX_ID, 0L)

	fun setUserLanguage(language: String?) = prefs.edit { putString(KEY_USER_LANGUAGE, language) }

	fun getUserLanguage(): String? = prefs.getString(KEY_USER_LANGUAGE, null)

	fun getZoomOn(): Boolean = prefs.getBoolean(KEY_ZOOM_ACTIVE, false)
	fun setZoomOn(isZoomActive: Boolean) = prefs.edit().putBoolean(KEY_ZOOM_ACTIVE, isZoomActive).apply()

	fun getRefreshButtonDisabledTimestamp(): Long = prefs.getLong(KEY_REFRESH_BUTTON_DISABLED_TIMESTAMP, -1L)
	fun setRefreshButtonDisabledTimestamp(timestamp: Long) = prefs.edit { putLong(KEY_REFRESH_BUTTON_DISABLED_TIMESTAMP, timestamp) }
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/dialog/InfoDialogFragment.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.dialog

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.os.bundleOf
import androidx.core.view.isVisible
import androidx.fragment.app.DialogFragment
import ch.admin.bag.covidcertificate.common.R
import ch.admin.bag.covidcertificate.common.config.InfoBoxModel
import ch.admin.bag.covidcertificate.common.databinding.DialogFragmentInfoBoxBinding
import ch.admin.bag.covidcertificate.common.util.UrlUtil

class InfoDialogFragment : DialogFragment() {

	companion object {
		private const val ARG_INFO_BOX_MODEL = "ARG_INFO_BOX_MODEL"

		fun newInstance(infoBoxModel: InfoBoxModel): InfoDialogFragment = InfoDialogFragment().apply {
			arguments = bundleOf(ARG_INFO_BOX_MODEL to infoBoxModel)
		}
	}

	private lateinit var infoBoxModel: InfoBoxModel

	private var _binding: DialogFragmentInfoBoxBinding? = null
	private val binding get() = _binding!!

	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		setStyle(STYLE_NO_TITLE, R.style.CovidCertificate_InfoDialog)
		infoBoxModel = requireArguments().getParcelable(ARG_INFO_BOX_MODEL)
			?: throw IllegalStateException("No infoBox information supplied to DialogFragment!")
	}

	override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
		_binding = DialogFragmentInfoBoxBinding.inflate(inflater, container, false)
		return binding.root
	}

	override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
		setupInfo()
	}

	override fun onDestroyView() {
		super.onDestroyView()
		_binding = null
	}

	private fun setupInfo() {
		binding.infoDialogTitle.text = infoBoxModel.title
		binding.infoDialogText.text = infoBoxModel.msg
		val hasCustomButton = !infoBoxModel.urlTitle.isNullOrEmpty()
		binding.infoDialogUrlButton.apply {
			text = infoBoxModel.urlTitle
			isVisible = hasCustomButton
			infoBoxModel.url?.let { url ->
				setOnClickListener { UrlUtil.openUrl(context, url) }
			}
		}
		binding.infoDialogCloseButton.apply {
			text = getString(if (hasCustomButton) R.string.accessibility_close_button else R.string.ok_button)
			setOnClickListener { if (this@InfoDialogFragment.isVisible) dismiss() }
		}
	}

	fun getInfoId(): Long = infoBoxModel.infoId
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/exception/HttpIOException.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.exception

import retrofit2.Response
import java.io.IOException

/**
 * A replacement for the retrofit2.HttpException that inherits from IOException instead of RuntimeException.
 * Since other request related exceptions (e.g. UnknownHost or SocketTimeout) extend IOException, this makes it easier to catch all
 * networking related exceptions in a single catch-clause.
 */
class HttpIOException(val response: Response<*>) : IOException(response.message()) {
	val code = response.code()
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/exception/TimeDeviationException.kt
================================================
package ch.admin.bag.covidcertificate.common.exception

class TimeDeviationException : IllegalStateException()

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/extensions/ContextExtensions.kt
================================================
/*
 * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.extensions

import android.content.Context
import android.content.res.Configuration
import java.util.*

fun Context.getDrawableIdentifier(drawableName: String) = resources.getIdentifier(drawableName, "drawable", packageName)

fun Context.updateLocale(languageKey: String? = null): Context {
	val config = Configuration()

	val locale = languageKey?.let {
		Locale(languageKey, "CH")
	} ?: Locale.getDefault()

	config.setLocale(locale)
	return createConfigurationContext(config)
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/extensions/DccCertExtensions.kt
================================================
package ch.admin.bag.covidcertificate.common.extensions

import ch.admin.bag.covidcertificate.sdk.core.extensions.firstPositiveResult
import ch.admin.bag.covidcertificate.sdk.core.extensions.vaccineDate
import ch.admin.bag.covidcertificate.sdk.core.extensions.validFromDate
import ch.admin.bag.covidcertificate.sdk.core.models.healthcert.eu.DccCert
import java.time.LocalDateTime

fun DccCert.getDate(): LocalDateTime? {
	var date = this.vaccinations?.firstOrNull()?.vaccineDate()

	if (date == null) {
		date = this.pastInfections?.firstOrNull()?.firstPositiveResult()
	}
	if (date == null) {
		date = this.tests?.firstOrNull()?.validFromDate()
	}
	return date
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/extensions/LifecycleOwnerExtensions.kt
================================================
/*
 * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.extensions

import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch

/**
 * Collect a flow, starting and cancelling the collection automatically when the lifecycle changes from or to STARTED
 */
fun <T> LifecycleOwner.collectWhenStarted(flow: Flow<T>, block: suspend (T) -> Unit) {
	lifecycleScope.launch {
		flow.flowWithLifecycle(lifecycle).collect {
			block(it)
		}
	}
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/extensions/OkHttpExtensions.kt
================================================
package ch.admin.bag.covidcertificate.common.extensions

import okhttp3.OkHttpClient
import java.util.concurrent.TimeUnit

fun OkHttpClient.Builder.setTimeouts(seconds: Long = 10): OkHttpClient.Builder {
	connectTimeout(seconds, TimeUnit.SECONDS)
	writeTimeout(seconds, TimeUnit.SECONDS)
	readTimeout(seconds, TimeUnit.SECONDS)
	return this
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/extensions/WindowExtensions.kt
================================================
package ch.admin.bag.covidcertificate.common.extensions

import android.view.Window
import android.view.WindowManager

fun Window.overrideScreenBrightness(override: Boolean) {
	if (override) {
		addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
	} else {
		clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
	}
	val layoutParams: WindowManager.LayoutParams = attributes
	layoutParams.screenBrightness = if (override) 1f else -1f
	attributes = layoutParams
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/faq/FaqAdapter.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.faq

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import ch.admin.bag.covidcertificate.common.faq.model.Faq
import ch.admin.bag.covidcertificate.common.faq.model.Header
import ch.admin.bag.covidcertificate.common.faq.model.IntroSection
import ch.admin.bag.covidcertificate.common.faq.model.Question

class FaqAdapter(val onLinkClickListener: ((String) -> Unit)? = null) : RecyclerView.Adapter<FaqViewHolder>() {

	private val items = mutableListOf<FaqItem>()

	override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FaqViewHolder {
		val inflater = LayoutInflater.from(parent.context)
		return when (viewType) {
			0 -> FaqViewHolder(inflater.inflate(HeaderItem.layoutResource, parent, false))
			1 -> FaqViewHolder(inflater.inflate(QuestionItem.layoutResource, parent, false))
			2 -> FaqViewHolder(inflater.inflate(IntroSectionItem.layoutResource, parent, false))
			else -> throw IllegalStateException("Unknown viewType $viewType in FaqAdapter")
		}
	}

	override fun onBindViewHolder(holder: FaqViewHolder, position: Int) {
		holder.bindItem(items[position]) { notifyItemChanged(position) }
	}

	override fun getItemCount(): Int = items.size

	override fun getItemViewType(position: Int): Int {
		return when (items[position]) {
			is HeaderItem -> 0
			is QuestionItem -> 1
			is IntroSectionItem -> 2
		}
	}

	fun setItems(items: List<Faq>) {
		this.items.clear()
		val newItems = items.mapNotNull {
			when (it) {
				is Header -> HeaderItem(it)
				is Question -> QuestionItem(it, onLinkClickListener)
				is IntroSection -> IntroSectionItem(it)
				else -> null
			}
		}
		this.items.addAll(newItems)
		notifyDataSetChanged()
	}

}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/faq/FaqFragment.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.faq

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.SimpleItemAnimator
import ch.admin.bag.covidcertificate.common.databinding.FragmentFaqBinding
import ch.admin.bag.covidcertificate.common.faq.model.Faq
import ch.admin.bag.covidcertificate.common.util.UrlUtil
import ch.admin.bag.covidcertificate.common.views.hideAnimated


abstract class FaqFragment : Fragment() {

	private var _binding: FragmentFaqBinding? = null
	private val binding get() = _binding!!

	lateinit var toolbar: Toolbar

	override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
		_binding = FragmentFaqBinding.inflate(inflater, container, false)
		return binding.root
	}

	override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
		super.onViewCreated(view, savedInstanceState)
		toolbar = binding.certificatesOverviewToolbar
		toolbar.setNavigationOnClickListener {
			parentFragmentManager.popBackStack()
		}

		setupFaqProvider()
	}

	override fun onDestroyView() {
		super.onDestroyView()
		_binding = null
	}

	protected abstract fun setupFaqProvider()

	protected fun setupFaqList(items: List<Faq>) {
		binding.faqLoadingView.hideAnimated()

		val recyclerView = binding.faqRecyclerView
		(recyclerView.itemAnimator as SimpleItemAnimator?)?.supportsChangeAnimations = false
		val layoutManager = LinearLayoutManager(recyclerView.context, LinearLayoutManager.VERTICAL, false)
		recyclerView.layoutManager = layoutManager
		val adapter = FaqAdapter { url: String ->
			context?.let { UrlUtil.openUrl(it, url) }
		}
		recyclerView.adapter = adapter
		adapter.setItems(items)
	}
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/faq/FaqItem.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.faq

import android.view.View
import androidx.core.view.doOnPreDraw
import androidx.core.view.isVisible
import ch.admin.bag.covidcertificate.common.R
import ch.admin.bag.covidcertificate.common.databinding.ItemFaqHeaderBinding
import ch.admin.bag.covidcertificate.common.databinding.ItemFaqIntroSectionBinding
import ch.admin.bag.covidcertificate.common.databinding.ItemFaqQuestionBinding
import ch.admin.bag.covidcertificate.common.extensions.getDrawableIdentifier
import ch.admin.bag.covidcertificate.common.faq.model.Header
import ch.admin.bag.covidcertificate.common.faq.model.IntroSection
import ch.admin.bag.covidcertificate.common.faq.model.Question

sealed class FaqItem {
	abstract fun bindView(view: View, onItemClickListener: (() -> Unit)? = null)
}

data class HeaderItem(val header: Header) : FaqItem() {
	companion object {
		val layoutResource = R.layout.item_faq_header
	}

	override fun bindView(view: View, onItemClickListener: (() -> Unit)?) {
		val binding = ItemFaqHeaderBinding.bind(view)
		binding.itemFaqHeaderTitle.text = header.title
		binding.itemFaqHeaderText.apply {
			text = header.subtitle
			isVisible = header.subtitle != null
		}

		val drawableId = header.iconName?.let { iconName ->
			view.context.getDrawableIdentifier(iconName)
		} ?: 0

		binding.itemFaqHeaderIllu.apply {
			setImageResource(drawableId)
			isVisible = drawableId != 0
		}
	}
}

data class QuestionItem(
	val question: Question,
	val onLinkClickListener: ((String) -> Unit)? = null,
) : FaqItem() {
	companion object {
		val layoutResource = R.layout.item_faq_question
	}

	override fun bindView(view: View, onItemClickListener: (() -> Unit)?) {
		val binding = ItemFaqQuestionBinding.bind(view)

		binding.root.setOnClickListener {
			question.isSelected = !question.isSelected
			view.doOnPreDraw { onItemClickListener?.invoke() }
		}
		binding.itemFaqQuestionTitle.text = question.question
		binding.itemFaqQuestionAnswer.apply {
			text = question.answer
			isVisible = question.isSelected
		}
		val hasLink = !question.linkTitle.isNullOrEmpty() && !question.linkUrl.isNullOrEmpty()
		(hasLink && question.isSelected).let { visible ->
			binding.itemFaqQuestionLinkLabel.isVisible = visible
			binding.itemFaqQuestionLink.isVisible = visible
		}

		if (hasLink) {
			binding.itemFaqQuestionLinkLabel.text = question.linkTitle
			binding.itemFaqQuestionLink.setOnClickListener { onLinkClickListener?.invoke(question.linkUrl!!) }
		} else {
			binding.itemFaqQuestionLink.setOnClickListener(null)
		}

		binding.itemFaqQuestionChevron.setImageResource(if (question.isSelected) R.drawable.ic_arrow_contract else R.drawable.ic_arrow_expand)
	}
}

data class IntroSectionItem(val introSection: IntroSection) : FaqItem() {
	companion object {
		val layoutResource = R.layout.item_faq_intro_section
	}

	override fun bindView(view: View, onItemClickListener: (() -> Unit)?) {
		val binding = ItemFaqIntroSectionBinding.bind(view)
		val drawableId = view.context.getDrawableIdentifier(introSection.iconName)
		binding.faqIntroSectionIcon.setImageResource(drawableId)
		binding.faqIntroSectionText.text = introSection.text
	}
}


================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/faq/FaqViewHolder.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.faq

import android.view.View
import androidx.recyclerview.widget.RecyclerView

class FaqViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
	fun bindItem(item: FaqItem, onItemClickListener: (() -> Unit)? = null) = item.bindView(itemView, onItemClickListener)
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/faq/model/Header.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.faq.model

import java.io.Serializable

interface Faq

data class Header(val iconName: String?, val title: String, val subtitle: String?) : Faq, Serializable

data class Question(
	val question: String,
	val answer: String,
	var isSelected: Boolean = false,
	val linkTitle: String? = null,
	val linkUrl: String? = null,
) : Faq, Serializable

data class IntroSection(val iconName: String, val text: String) : Faq, Serializable

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/html/BuildInfo.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.html

import java.io.Serializable

data class BuildInfo(
	val appName: String,
	val versionName: String,
	val buildTime: Long,
	val flavor: String,
	val agbUrl: String,
	val appIdentifier: String,
) : Serializable


================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/html/ImprintFragment.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.html

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.annotation.StringRes
import androidx.fragment.app.Fragment
import androidx.fragment.app.commit
import ch.admin.bag.covidcertificate.common.R
import ch.admin.bag.covidcertificate.common.databinding.FragmentHtmlBinding
import ch.admin.bag.covidcertificate.common.settings.SettingsFragment
import ch.admin.bag.covidcertificate.common.util.AssetUtil
import ch.admin.bag.covidcertificate.common.util.UrlUtil
import ch.admin.bag.covidcertificate.common.views.hideAnimated
import java.util.*

class ImprintFragment : Fragment() {

	companion object {
		private const val COVID_CERT_IMPRESSUM_PREFIX = "ccert://"

		private const val ARG_BASE_URL = "ARG_BASE_URL"
		private const val ARG_BUILD_INFO = "ARG_BUILD_INFO"
		private const val ARG_DATA = "ARG_DATA"
		private const val ARG_TITLE = "ARG_TITLE"
		private const val ARG_SETTINGS = "ARG_SETTINGS"

		fun newInstance(
			titleRes: Int,
			buildInfo: BuildInfo,
			baseUrl: String? = null,
			data: String? = null,
			showSettings: Boolean = true
		): ImprintFragment {
			val fragment = ImprintFragment()
			fragment.arguments = Bundle().apply {
				putString(ARG_BASE_URL, baseUrl)
				putSerializable(ARG_BUILD_INFO, buildInfo)
				putString(ARG_DATA, data)
				putInt(ARG_TITLE, titleRes)
				putBoolean(ARG_SETTINGS, showSettings)
			}
			return fragment
		}
	}

	private var _binding: FragmentHtmlBinding? = null
	private val binding get() = _binding!!

	private lateinit var baseUrl: String
	private var data: String? = null
	private var buildInfo: BuildInfo? = null

	@StringRes
	private var titleRes = 0

	private var showSettings = false

	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		requireArguments().apply {
			baseUrl = getString(ARG_BASE_URL) ?: AssetUtil.getImpressumBaseUrl(requireContext())
			buildInfo = getSerializable(ARG_BUILD_INFO) as? BuildInfo?
			data = getString(ARG_DATA) ?: buildInfo?.let { AssetUtil.getImpressumHtml(requireContext(), it) }
			titleRes = getInt(ARG_TITLE)
			showSettings = getBoolean(ARG_SETTINGS)
		}
	}

	override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
		_binding = FragmentHtmlBinding.inflate(inflater, container, false)
		return binding.root
	}

	override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
		super.onViewCreated(view, savedInstanceState)

		val toolbar = binding.htmlToolbar
		toolbar.setTitle(titleRes)
		toolbar.setNavigationOnClickListener { parentFragmentManager.popBackStack() }

		if (showSettings) {
			toolbar.inflateMenu(R.menu.imprint)
			toolbar.setOnMenuItemClickListener { item ->
				when (item.itemId) {
					R.id.menu_settings -> parentFragmentManager.commit {
						setCustomAnimations(R.anim.slide_enter, R.anim.slide_exit, R.anim.slide_pop_enter, R.anim.slide_pop_exit)
						replace(id, SettingsFragment.newInstance())
						addToBackStack(SettingsFragment::class.java.canonicalName)
					}
					else -> throw UnsupportedOperationException()
				}
				true
			}
		}

		val web = binding.htmlWebview
		val loadingSpinner = binding.loadingSpinner

		web.webViewClient = object : WebViewClient() {
			override fun onPageFinished(view: WebView, url: String) {
				loadingSpinner.hideAnimated()
				super.onPageFinished(view, url)
			}

			override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
				if (baseUrl == url) return true
				if (url.toLowerCase(Locale.ENGLISH).startsWith(COVID_CERT_IMPRESSUM_PREFIX)) {
					val buildInfo = buildInfo ?: throw IllegalStateException("No BuildInfo supplied for imprint")
					val strippedUrl = url.substring(COVID_CERT_IMPRESSUM_PREFIX.length)
					val htmlFragment = newInstance(
						R.string.impressum_title,
						buildInfo,
						baseUrl,
						AssetUtil.loadImpressumHtmlFile(view.context, strippedUrl, buildInfo),
						false
					)
					parentFragmentManager.beginTransaction()
						.setCustomAnimations(
							R.anim.slide_enter, R.anim.slide_exit, R.anim.slide_pop_enter,
							R.anim.slide_pop_exit
						)
						.replace(id, htmlFragment)
						.addToBackStack(ImprintFragment::class.java.canonicalName)
						.commit()
					return true
				}
				UrlUtil.openUrl(context, url)
				return true
			}
		}
		if (data != null) {
			data?.let { web.loadDataWithBaseURL(baseUrl, it, "text/html", "UTF-8", null) }
		} else {
			web.loadUrl(baseUrl)
		}
	}

	override fun onDestroyView() {
		super.onDestroyView()
		_binding = null
	}

}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/net/ConfigRepository.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.net

import android.content.Context
import android.os.Build
import ch.admin.bag.covidcertificate.common.BuildConfig
import ch.admin.bag.covidcertificate.common.config.ConfigModel
import ch.admin.bag.covidcertificate.common.data.ConfigSecureStorage
import ch.admin.bag.covidcertificate.common.extensions.setTimeouts
import ch.admin.bag.covidcertificate.common.util.AssetUtil
import ch.admin.bag.covidcertificate.sdk.android.CovidCertificateSdk
import ch.admin.bag.covidcertificate.sdk.android.data.Config
import ch.admin.bag.covidcertificate.sdk.android.net.CertificatePinning
import ch.admin.bag.covidcertificate.sdk.android.net.interceptor.JwsInterceptor
import ch.admin.bag.covidcertificate.sdk.android.net.interceptor.UserAgentInterceptor
import ch.admin.bag.covidcertificate.sdk.android.utils.SingletonHolder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.Cache
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.HttpException
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory

class ConfigRepository private constructor(private val configSpec: ConfigSpec) {

	companion object : SingletonHolder<ConfigRepository, ConfigSpec>(::ConfigRepository) {
		private const val APP_VERSION_PREFIX_ANDROID = "android-"
		private const val OS_VERSION_PREFIX_ANDROID = "android"

		private const val MIN_LOAD_WAIT_TIME = 60 * 60 * 1000L // 1h
		private const val MAX_AGE_STATUS_VALID_CACHED_CONFIG = 48 * 60 * 60 * 1000L // 48h

		fun getCurrentConfig(context: Context) =
			ConfigSecureStorage.getInstance(context).getConfig() ?: AssetUtil.loadDefaultConfig(context)
	}

	private val configService: ConfigService
	private val storage = ConfigSecureStorage.getInstance(configSpec.context)

	init {
		val rootCa = CovidCertificateSdk.getRootCa(configSpec.context)
		val expectedCommonName = CovidCertificateSdk.getExpectedCommonName()
		val okHttpBuilder = OkHttpClient.Builder()
			.certificatePinner(CertificatePinning.pinner)
			.addInterceptor(JwsInterceptor(rootCa, expectedCommonName))
			.addInterceptor(UserAgentInterceptor(Config.userAgent))
			.setTimeouts()

		val cacheSize = 5 * 1024 * 1024 // 5 MB
		val cache = Cache(configSpec.context.cacheDir, cacheSize.toLong())
		okHttpBuilder.cache(cache)

		if (BuildConfig.DEBUG) {
			val httpInterceptor = HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
			okHttpBuilder.addInterceptor(httpInterceptor)
		}

		configService = Retrofit.Builder()
			.baseUrl(configSpec.baseUrl)
			.client(okHttpBuilder.build())
			.addConverterFactory(MoshiConverterFactory.create())
			.build()
			.create(ConfigService::class.java)
	}

	suspend fun loadConfig(context: Context): ConfigModel? {
		val requestTimeStamp = System.currentTimeMillis()
		val appVersion = APP_VERSION_PREFIX_ANDROID + configSpec.versionName
		val osVersion = OS_VERSION_PREFIX_ANDROID + Build.VERSION.SDK_INT
		val buildNumber = configSpec.buildTime
		val versionString = "appversion=$appVersion&osversion=$osVersion&buildnr=$buildNumber"
		var config =
			if (storage.getConfigLastSuccessTimestamp() + MIN_LOAD_WAIT_TIME <= System.currentTimeMillis() || versionString != storage.getConfigLastSuccessAppAndOSVersion()) {
				try {
					val response = withContext(Dispatchers.IO) { configService.getConfig(appVersion, osVersion, buildNumber) }
					if (!response.isSuccessful) throw HttpException(response)
					response.body()?.let { storage.updateConfigData(it, requestTimeStamp, versionString) }
					response.body()
				} catch (e: Exception) {
					e.printStackTrace()
					null
				}
			} else null

		if (config == null) config = storage.getConfig()
		if (config == null) config = AssetUtil.loadDefaultConfig(context)

		// If the config has disabled the refresh button check if it's the first time and if so, store the timestamp
		if (config?.refreshButtonDisabled == true) {
			if (storage.getRefreshButtonDisabledTimestamp() < 0L) {
				storage.setRefreshButtonDisabledTimestamp(System.currentTimeMillis())
			}
		} else {
			storage.setRefreshButtonDisabledTimestamp(-1L)
		}

		return config
	}

}

class ConfigSpec(val context: Context, val baseUrl: String, val versionName: String, val buildTime: String)

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/net/ConfigService.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.net

import ch.admin.bag.covidcertificate.common.config.ConfigModel
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Headers
import retrofit2.http.Query

interface ConfigService {

	@Headers("Accept: application/json+jws")
	@GET("config")
	suspend fun getConfig(
		@Query("appversion") appVersion: String,
		@Query("osversion") osVersion: String,
		@Query("buildnr") buildNumber: String
	): Response<ConfigModel>

}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/onboarding/BaseOnboardingActivity.kt
================================================
/*
 * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.onboarding

import android.os.Bundle
import androidx.viewpager2.adapter.FragmentStateAdapter
import ch.admin.bag.covidcertificate.common.BaseActivity
import ch.admin.bag.covidcertificate.common.R
import ch.admin.bag.covidcertificate.common.databinding.ActivityOnboardingBinding

abstract class BaseOnboardingActivity : BaseActivity() {

	companion object {
		const val EXTRA_ONBOARDING_TYPE = "EXTRA_ONBOARDING_TYPE"
	}

	private lateinit var binding: ActivityOnboardingBinding
	private lateinit var pagerAdapter: FragmentStateAdapter

	protected abstract fun getPagerAdapter(): FragmentStateAdapter?

	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)

		val pagerAdapter = getPagerAdapter()
		if (pagerAdapter == null) {
			finish()
			return
		}

		binding = ActivityOnboardingBinding.inflate(layoutInflater)
		setContentView(binding.root)

		binding.viewPager.isUserInputEnabled = false

		this.pagerAdapter = pagerAdapter
		binding.viewPager.adapter = pagerAdapter
	}

	fun continueToNextPage() {
		val currentItem: Int = binding.viewPager.currentItem
		if (currentItem < pagerAdapter.itemCount - 1) {
			binding.viewPager.setCurrentItem(currentItem + 1, true)
		} else {
			setResult(RESULT_OK)
			finish()
			overridePendingTransition(R.anim.fragment_open_enter, R.anim.fragment_open_exit)
		}
	}


}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/onboarding/SimpleOnboardingPagerAdapter.kt
================================================
/*
 * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.onboarding

import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter

class SimpleOnboardingPagerAdapter(
	fragmentActivity: FragmentActivity,
	private vararg val fragmentProviders: FragmentProvider
) : FragmentStateAdapter(fragmentActivity) {

	override fun createFragment(position: Int) = fragmentProviders[position].provide()

	override fun getItemCount() = fragmentProviders.size

	fun interface FragmentProvider {
		fun provide(): Fragment
	}
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/qr/CameraPermissionExplanationDialog.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.qr

import android.content.Context
import android.graphics.Paint
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import ch.admin.bag.covidcertificate.common.R

class CameraPermissionExplanationDialog(context: Context) : AlertDialog(context) {

	private var grantCameraAccessClickListener: View.OnClickListener? = null

	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		setContentView(R.layout.dialog_camera_permission_explanation)
		window?.apply {
			setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
			setBackgroundDrawableResource(R.drawable.bg_dialog)
		}
		findViewById<TextView>(R.id.camera_permission_dialog_ok_button)?.apply {
			paintFlags = paintFlags or Paint.UNDERLINE_TEXT_FLAG
			setOnClickListener { v: View? ->
				dismiss()
				grantCameraAccessClickListener?.onClick(v)
			}
		}
		findViewById<View>(R.id.camera_permission_dialog_close_button)?.setOnClickListener { _ -> cancel() }
	}

	fun setGrantCameraAccessClickListener(listener: View.OnClickListener?) {
		grantCameraAccessClickListener = listener
	}

}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/qr/KittlerBinarizer.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */
package ch.admin.bag.covidcertificate.common.qr

import com.google.zxing.LuminanceSource
import com.google.zxing.common.BitMatrix
import com.google.zxing.common.GlobalHistogramBinarizer
import okhttp3.internal.and
import kotlin.math.abs

/*
 *Use a Kittler Binarizer described here //http://www.iztok-jr-fister.eu/static/publications/39.pdf
 *
 *  */

class KittlerBinarizer(luminanceSource: LuminanceSource) : GlobalHistogramBinarizer(luminanceSource) {

	override fun getBlackMatrix(): BitMatrix {
		val source = luminanceSource
		val width = source.width
		val height = source.height
		var count = 0
		var totalcount = 0
		val matrix = BitMatrix(width, height)
		val localLuminanceSource = source.matrix
		val threshold = estimateThreshold(localLuminanceSource, width, height)
		(0 until height).forEach { y ->
			val offset = y * width
			(0 until width).forEach { x ->
				totalcount++
				val pixel = localLuminanceSource[offset + x] and 0xFF

				if (pixel < threshold) {
					count++
					matrix.set(x, y)
				}
			}

		}
		return matrix
	}

	private fun estimateThreshold(localLuminanceSource: ByteArray, width: Int, height: Int): Int {
		var E = 0L
		var EF = 0L
		(1 until height - 1).forEach { y ->
			val offset = y * width
			(1 until width - 1).forEach { x ->
				val grey = localLuminanceSource[offset + x] and 0xFF
				val grey1 = localLuminanceSource[offset + x - 1] and 0xFF
				val grey2 = localLuminanceSource[offset + x + 1] and 0xFF
				val grey3 = localLuminanceSource[offset + x - width] and 0xFF
				val grey4 = localLuminanceSource[offset + x + width] and 0xFF

				val Ex = abs(grey1 - grey2)
				val Ey = abs(grey3 - grey4)
				val exy = Math.max(Ex, Ey)
				E += exy
				EF += exy * grey
			}
		}
		if (E == 0L) {
			return 128
		}
		return ((EF / E) - 1L).toInt()
	}
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/qr/QRCodeReaderHelper.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.qr

import android.app.ActivityManager
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.pdf.PdfRenderer
import android.os.ParcelFileDescriptor
import com.google.zxing.*
import com.google.zxing.common.GlobalHistogramBinarizer
import com.google.zxing.common.HybridBinarizer
import java.io.File
import java.lang.Integer.min
import kotlin.math.roundToInt


object QRCodeReaderHelper {
	private val hints = mapOf(
		DecodeHintType.POSSIBLE_FORMATS to arrayListOf(BarcodeFormat.QR_CODE),
		DecodeHintType.TRY_HARDER to true,
	)

	private const val PDF_PAGE_LIMIT = 5
	private val reader = MultiFormatReader().apply { setHints(hints) }

	fun decodeQrCode(bitmap: Bitmap): String? {
		val intArray = IntArray(bitmap.width * bitmap.height)
		bitmap.getPixels(intArray, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)
		val source: LuminanceSource = RGBLuminanceSource(bitmap.width, bitmap.height, intArray)

		// First try with hybrid binarizer, then with global histogram binarizer. Same as in the camera scanner
		return decodeQrCodeWithBinarizer(HybridBinarizer(source))
			?: decodeQrCodeWithBinarizer(GlobalHistogramBinarizer(source))
	}

	fun pdfToBitmaps(context: Context, pdfFile: File): Sequence<Bitmap> = sequence {
		try {
			PdfRenderer(ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY)).use { renderer ->
				val pageCount = renderer.pageCount

				val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
				val memoryInfo = ActivityManager.MemoryInfo().also { activityManager.getMemoryInfo(it) }

				for (scale in listOf(1f, context.resources.displayMetrics.densityDpi / 72f, 3f, 5f, 7f, 9f)) {
					for (i in 0 until min(pageCount, PDF_PAGE_LIMIT)) {
						renderer.openPage(i).use { page ->

							// PDF width/height are given in "points pt" such that 1 pt = 1/72 inch
							// => 72 "dots-per-inch dpi" <==> scale = 1
							val pixelWidth = (scale * page.width).roundToInt()
							val pixelHeight = (scale * page.height).roundToInt()


							if (scale == 1f || !memoryInfo.lowMemory) {
								// Only yield the scaled bitmap if the system is not considered to be in low memory mode
								// On some devices, this bitmap can get up to 50MB due to the large scale factor
								page.renderToBitmap(pixelWidth, pixelHeight).use {
									yield(it)
								}
							}
						}
					}

				}

			}
		} catch (ex: Exception) {
			ex.printStackTrace()
		}
	}

	private fun decodeQrCodeWithBinarizer(binarizer: Binarizer): String? {
		val binaryBitmap = BinaryBitmap(binarizer)

		try {
			val result: Result = reader.decodeWithState(binaryBitmap)
			return result.text
		} catch (e: NotFoundException) {
			e.printStackTrace()
		} catch (e: ChecksumException) {
			e.printStackTrace()
		} catch (e: FormatException) {
			e.printStackTrace()
		}
		return null
	}

	private fun PdfRenderer.Page.renderToBitmap(pixelWidth: Int, pixelHeight: Int): Bitmap {
		val bitmap = Bitmap.createBitmap(pixelWidth, pixelHeight, Bitmap.Config.ARGB_8888)

		// Make sure the bitmap's background is not transparent (which can cause issues for QR code detection)
		bitmap.eraseColor(Color.WHITE)

		// Draw the page onto the bitmap. Internally, this will scale the page to fit the bitmap (unless transform != null).
		this.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_PRINT)

		// reduce pixel size to avoid memory issues down the line
		val bitmapR = bitmap.copy(Bitmap.Config.RGB_565, false)
		bitmap.recycle()

		return bitmapR
	}

	private inline fun Bitmap.use(block: (Bitmap) -> Unit) {
		try {
			block(this)
		} finally {
			this.recycle()
		}
	}
}



================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/qr/QrScanFragment.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.qr

import android.Manifest
import android.annotation.SuppressLint
import android.content.pm.PackageManager
import android.graphics.drawable.GradientDrawable
import android.graphics.drawable.LayerDrawable
import android.os.Bundle
import android.view.View
import android.widget.ImageButton
import android.widget.TextView
import androidx.annotation.ColorRes
import androidx.appcompat.widget.Toolbar
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.lifecycle.liveData
import ch.admin.bag.covidcertificate.common.R
import ch.admin.bag.covidcertificate.common.data.ConfigSecureStorage
import ch.admin.bag.covidcertificate.common.util.ErrorHelper
import ch.admin.bag.covidcertificate.common.util.ErrorState
import ch.admin.bag.covidcertificate.sdk.core.models.state.StateError
import ch.ubique.qrscanner.scanner.ErrorCodes
import ch.ubique.qrscanner.scanner.ScanningMode
import ch.ubique.qrscanner.state.DecodingState
import ch.ubique.qrscanner.util.CameraUtil
import ch.ubique.qrscanner.view.QrScannerView
import ch.ubique.qrscanner.zxing.decoder.GlobalHistogramImageDecoder
import ch.ubique.qrscanner.zxing.decoder.HybridImageDecoder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive

abstract class QrScanFragment : Fragment() {

	companion object {
		private const val STATE_IS_TORCH_ON = "STATE_IS_TORCH_ON"
		private const val PERMISSION_REQUEST_CAMERA = 13
		private const val MIN_ERROR_VISIBILITY = 1000L

		private const val QR_CODE_ERROR_WRONG_FORMAT = "Q|YWF"
		private const val QR_CODE_ERROR_READ_FAILED = "Q|IRF"
	}

	// These need to be set by implementing classes during onCreateView. That's why they are not private.
	protected lateinit var toolbar: Toolbar
	protected lateinit var flashButton: ImageButton
	protected lateinit var errorView: View
	protected lateinit var errorCodeView: TextView
	protected lateinit var zoomButton: ImageButton

	protected lateinit var invalidCodeText: TextView
	protected lateinit var viewFinderTopLeftIndicator: View
	protected lateinit var viewFinderTopRightIndicator: View
	protected lateinit var viewFinderBottomLeftIndicator: View
	protected lateinit var viewFinderBottomRightIndicator: View
	protected lateinit var qrCodeScanner: QrScannerView
	protected lateinit var cutOut: View
	abstract val viewFinderColor: Int

	abstract val viewFinderErrorColor: Int
	abstract val torchOnDrawable: Int
	abstract val torchOffDrawable: Int
	abstract val zoomOnDrawable: Int
	abstract val zoomOffDrawable: Int
	private var lastUIErrorUpdate = 0L

	private var cameraPermissionState = CameraPermissionState.REQUESTING
	private val secureStorage by lazy { ConfigSecureStorage.getInstance(requireContext()) }
	private var cameraPermissionExplanationDialog: CameraPermissionExplanationDialog? = null
	private var isTorchOn: Boolean = false

	private val autoFocusClockLiveData = liveData(Dispatchers.IO) {
		while (currentCoroutineContext().isActive) {
			emit(Unit)
			delay(3 * 1000L)
		}
	}

	override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
		super.onViewCreated(view, savedInstanceState)
		isTorchOn = savedInstanceState?.getBoolean(STATE_IS_TORCH_ON, isTorchOn) ?: isTorchOn
		toolbar.setNavigationOnClickListener { parentFragmentManager.popBackStack() }

		// Wait for the views to be properly laid out
		qrCodeScanner.post {
			initializeCamera()
		}
	}

	override fun onResume() {
		super.onResume()

		// Check permission in onResume to automatically handle the user returning from the system settings.
		// Be careful to avoid popup loops, since our fragment is resumed whenever the user returns from the dialog!
		checkCameraPermission()

		setFlashAndButtonStyle()
	}

	override fun onSaveInstanceState(outState: Bundle) {
		super.onSaveInstanceState(outState)
		outState.putBoolean(STATE_IS_TORCH_ON, isTorchOn)
	}

	abstract fun decodeQrCodeData(qrCodeData: String, onDecodeSuccess: () -> Unit, onDecodeError: (StateError) -> Unit)

	override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String?>, grantResults: IntArray) {
		if (requestCode == PERMISSION_REQUEST_CAMERA) {
			val isGranted = grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED

			cameraPermissionState = if (isGranted) CameraPermissionState.GRANTED else CameraPermissionState.DENIED
			refreshView()
		}
	}

	protected fun activateCamera() {
		if (!isAdded || !qrCodeScanner.isAttachedToWindow) return

		autoFocusClockLiveData.observe(viewLifecycleOwner) {
			autoFocus()
		}

		qrCodeScanner.activateCamera()
	}

	protected fun deactivateCamera() {
		if (!isAdded || !qrCodeScanner.isAttachedToWindow) return

		autoFocusClockLiveData.removeObservers(viewLifecycleOwner)

		qrCodeScanner.deactivateCamera()
	}

	@SuppressLint("ClickableViewAccessibility")
	private fun initializeCamera() {
		if (!isAdded || !qrCodeScanner.isAttachedToWindow) return

		setScannerCallback()
		qrCodeScanner.setImageDecoders(GlobalHistogramImageDecoder(), HybridImageDecoder())
		qrCodeScanner.setScanningMode(ScanningMode.PARALLEL)
		qrCodeScanner.setFocusOnTap(true)
		qrCodeScanner.setCameraStateCallback { isActive ->
			if (isActive) {
				qrCodeScanner.isVisible = true
				setupZoomButton()
				setupFlashButton()
			} else {
				qrCodeScanner.isVisible = false
			}
		}
	}

	protected fun setScannerCallback() {
		qrCodeScanner.setScannerCallback { state ->
			when (state) {
				is DecodingState.NotFound -> view?.post { updateQrCodeScannerState(QrScannerState.NO_CODE_FOUND) }
				is DecodingState.Decoded -> {
					val qrCodeData = state.content
					decodeQrCodeData(
						qrCodeData,
						onDecodeSuccess = {
							// Once successfully decoded, clear the analyzer from stopping more frames being
							// analyzed and possibly decoded successfully
							qrCodeScanner.setScannerCallback(null)

							view?.post { updateQrCodeScannerState(QrScannerState.VALID) }
						},
						onDecodeError = { error ->
							view?.post { handleInvalidQRCodeExceptions(error) }
						}
					)
				}
				is DecodingState.Error -> {
					val stateError = if (state.errorCode == ErrorCodes.INPUT_WRONG_FORMAT) {
						StateError(QR_CODE_ERROR_WRONG_FORMAT)
					} else {
						StateError(QR_CODE_ERROR_READ_FAILED)
					}
					handleInvalidQRCodeExceptions(stateError)
				}
			}
		}
	}

	private fun setZoom() {
		if (secureStorage.getZoomOn()) {
			qrCodeScanner.setLinearZoom(1f)
		} else {
			qrCodeScanner.setLinearZoom(0f)
		}
	}

	private fun autoFocus() {
		val centerX = cutOut.left + cutOut.width / 2.0f
		val centerY = cutOut.top + cutOut.height / 2.0f
		qrCodeScanner.startAutofocus(centerX, centerY)
	}

	private fun checkCameraPermission() {
		val isGranted = CameraUtil.hasCameraPermission(requireContext())

		if (isGranted) {
			cameraPermissionState = CameraPermissionState.GRANTED
		}
		// Do not request the permission again if the last time we tried the user denied it.
		// I.e. don't show the popup but the error view
		else if (cameraPermissionState != CameraPermissionState.DENIED) {
			cameraPermissionState = CameraPermissionState.REQUESTING
		}
		refreshView()
	}

	private fun refreshView() {
		when (cameraPermissionState) {
			CameraPermissionState.GRANTED -> {
				errorView.isVisible = false
			}
			CameraPermissionState.REQUESTING -> {
				errorView.isVisible = false
				showCameraPermissionExplanationDialog()
			}
			CameraPermissionState.CANCELLED, CameraPermissionState.DENIED -> {
				errorView.isVisible = true
				ErrorHelper.updateErrorView(errorView, ErrorState.CAMERA_ACCESS_DENIED, null, context)
			}
		}
		updateQrCodeScannerState(QrScannerState.NO_CODE_FOUND)
	}

	private fun showCameraPermissionExplanationDialog() {
		if (cameraPermissionExplanationDialog?.isShowing == true) {
			return
		}

		cameraPermissionExplanationDialog = CameraPermissionExplanationDialog(requireContext()).apply {
			setOnCancelListener {
				cameraPermissionState = CameraPermissionState.CANCELLED
				refreshView()
			}
			setGrantCameraAccessClickListener {
				requestPermissions(arrayOf(Manifest.permission.CAMERA), PERMISSION_REQUEST_CAMERA)
			}
			setOnDismissListener {
				cameraPermissionExplanationDialog = null
			}
			show()
		}
	}

	private fun setupFlashButton() {
		val cameraInfo = qrCodeScanner.getCameraInfo() ?: return

		if (cameraInfo.hasFlashUnit()) {
			flashButton.isVisible = true
			setFlashAndButtonStyle()
		} else {
			flashButton.isVisible = false
		}

		flashButton.setOnClickListener {
			isTorchOn = !flashButton.isSelected
			setFlashAndButtonStyle()
		}
		zoomButton.setOnClickListener {
			secureStorage.setZoomOn(!secureStorage.getZoomOn())
			setupZoomButton()
		}
	}

	private fun setFlashAndButtonStyle() {
		qrCodeScanner.setFlash(isTorchOn)
		val drawableId = if (isTorchOn) torchOnDrawable else torchOffDrawable
		flashButton.isSelected = isTorchOn
		flashButton.setImageResource(drawableId)
	}

	private fun setupZoomButton() {
		if (requireContext().packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_AUTOFOCUS)) {
			zoomButton.isVisible = false
		} else {
			val isZoomOn = secureStorage.getZoomOn()
			zoomButton.isVisible = true
			val drawableId = if (isZoomOn) zoomOnDrawable else zoomOffDrawable
			zoomButton.isSelected = isZoomOn
			zoomButton.setImageResource(drawableId)
			setZoom()
		}
	}

	private fun handleInvalidQRCodeExceptions(error: StateError?) {
		updateQrCodeScannerState(QrScannerState.INVALID_FORMAT, error?.code)
	}

	private fun updateQrCodeScannerState(qrScannerState: QrScannerState, errorCode: String? = null) {
		if (!isAdded) return

		val currentTime = System.currentTimeMillis()
		if (lastUIErrorUpdate > currentTime - MIN_ERROR_VISIBILITY && qrScannerState == QrScannerState.NO_CODE_FOUND) {
			return
		}

		lastUIErrorUpdate = currentTime
		var color: Int = viewFinderColor
		when (qrScannerState) {
			QrScannerState.VALID, QrScannerState.NO_CODE_FOUND -> {
				invalidCodeText.isVisible = false
				errorCodeView.isVisible = false
			}
			QrScannerState.INVALID_FORMAT -> {
				invalidCodeText.isVisible = true
				errorCodeView.isVisible = errorCode != null
				errorCodeView.text = errorCode
				color = viewFinderErrorColor
			}
		}

		setIndicatorColor(viewFinderTopLeftIndicator, color)
		setIndicatorColor(viewFinderTopRightIndicator, color)
		setIndicatorColor(viewFinderBottomLeftIndicator, color)
		setIndicatorColor(viewFinderBottomRightIndicator, color)
	}

	private fun setIndicatorColor(indicator: View, @ColorRes color: Int) {
		val drawable = indicator.background as LayerDrawable
		val stroke = drawable.findDrawableByLayerId(R.id.indicator) as GradientDrawable
		stroke.setStroke(
			resources.getDimensionPixelSize(R.dimen.qr_scanner_indicator_stroke_width),
			resources.getColor(color, null)
		)
	}

	enum class CameraPermissionState {
		GRANTED,
		REQUESTING,
		CANCELLED,
		DENIED,
	}
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/qr/QrScannerState.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.qr

enum class QrScannerState {
	NO_CODE_FOUND,
	VALID,
	INVALID_FORMAT,
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/settings/SettingsFragment.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.settings

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import ch.admin.bag.covidcertificate.common.R
import ch.admin.bag.covidcertificate.common.data.ConfigSecureStorage
import ch.admin.bag.covidcertificate.common.databinding.FragmentSettingsBinding
import ch.admin.bag.covidcertificate.common.databinding.ItemLanguageOptionBinding
import ch.admin.bag.covidcertificate.common.util.LocaleUtil.DEFAULT_COUNTRY
import java.util.*

class SettingsFragment : Fragment() {

	companion object {
		fun newInstance(): SettingsFragment {
			return SettingsFragment()
		}
	}

	override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
		return FragmentSettingsBinding.inflate(inflater, container, false).apply {
			settingsToolbar.setNavigationOnClickListener { parentFragmentManager.popBackStack() }

			val currentLanguage = getString(R.string.language_key)

			listOf("de", "fr", "it", "rm", "en").forEach { language ->
				ItemLanguageOptionBinding.inflate(inflater, languageList, true).apply {
					val locale = Locale(language, DEFAULT_COUNTRY)
					radiobutton.text = locale.getDisplayLanguage(locale).capitalize(locale)
					radiobutton.isChecked = locale.language == currentLanguage

					radiobutton.setOnCheckedChangeListener { _, isChecked ->
						if (isChecked) {
							updateLanguage(language)
						}
					}
				}
			}
		}.root
	}

	private fun updateLanguage(language: String) {
		ConfigSecureStorage.getInstance(requireContext()).setUserLanguage(language)
		requireActivity().recreate()
	}

}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/util/AssetUtil.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.util

import android.content.Context
import ch.admin.bag.covidcertificate.common.R
import ch.admin.bag.covidcertificate.common.config.ConfigModel
import ch.admin.bag.covidcertificate.common.html.BuildInfo
import com.squareup.moshi.Moshi
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader
import java.text.SimpleDateFormat
import java.util.*

object AssetUtil {

	private const val PREFIX_ASSET_FILE = "file:///android_asset/"
	private const val FOLDER_NAME_IMPRESSUM = "impressum/"
	private const val FILE_NAME_IMPRESSUM = "impressum.html"
	private const val FOLDER_NAME_DISCLAIMER = "disclaimer/"
	private const val DISCLAIMER_FALLBACK_LANGUAGE = "de"
	private const val FILE_NAME_DATA_PROTECTION_STATEMENT = "data_protection_statement.html"
	private const val FILE_NAME_TERMS_OF_USE = "terms_of_use.html"

	private const val REPLACE_STRING_APP_NAME = "{APP_NAME}"
	private const val REPLACE_STRING_VERSION = "{VERSION}"
	private const val REPLACE_STRING_APPVERSION = "{APPVERSION}"
	private const val REPLACE_STRING_RELEASEDATE = "{RELEASEDATE}"
	private const val REPLACE_STRING_BUILDNR = "{BUILD}"
	private const val REPLACE_STRING_LAW_LINK = "{LAW_LINK}"
	private const val REPLACE_STRING_APP_IDENTIFIER = "{PARAM_APP_IDENTIFIER}"

	private val RELEASE_DATE_FORMAT = SimpleDateFormat("dd.MM.yyyy").apply { timeZone = TimeZone.getTimeZone("Europe/Zurich") }

	private const val ASSET_FILENAME_DEFAULT_CONFIG = "faq/config.json"

	private fun loadAssetJson(context: Context, filename: String): String? {
		return try {
			val inputStream = context.assets.open(filename)
			val json = inputStream.bufferedReader().use { it.readText() }
			inputStream.close()
			json
		} catch (ex: IOException) {
			ex.printStackTrace()
			null
		}
	}

	fun loadDefaultConfig(context: Context): ConfigModel? = loadAssetJson(context, ASSET_FILENAME_DEFAULT_CONFIG)?.let {
		Moshi.Builder().build().adapter(ConfigModel::class.java).fromJson(it)
	}

	fun getImpressumBaseUrl(context: Context): String {
		return PREFIX_ASSET_FILE + getFolderNameImpressum(context)
	}

	private fun getFolderNameImpressum(context: Context): String {
		return FOLDER_NAME_IMPRESSUM + context.getString(R.string.language_key) + "/"
	}

	fun getImpressumHtml(context: Context, buildInfo: BuildInfo): String? {
		return loadImpressumHtmlFile(context, FILE_NAME_IMPRESSUM, buildInfo)
	}

	fun loadImpressumHtmlFile(
		context: Context,
		filename: String,
		buildInfo: BuildInfo,
	): String? {
		return try {
			val html = StringBuilder()
			BufferedReader(InputStreamReader(context.assets.open(getFolderNameImpressum(context) + filename))).use { reader ->
				var line: String?
				while (reader.readLine().also { line = it } != null) {
					html.append(line)
				}
			}
			var impressum = html.toString()
			val buildString = "${buildInfo.buildTime} / ${buildInfo.flavor}"
			impressum = impressum.replace(REPLACE_STRING_VERSION, buildInfo.versionName)
			impressum = impressum.replace(REPLACE_STRING_APPVERSION, buildInfo.versionName)
			impressum = impressum.replace(REPLACE_STRING_RELEASEDATE, RELEASE_DATE_FORMAT.format(buildInfo.buildTime))
			impressum = impressum.replace(REPLACE_STRING_BUILDNR, buildString)
			impressum = impressum.replace(REPLACE_STRING_APP_NAME, buildInfo.appName)
			impressum = impressum.replace(REPLACE_STRING_LAW_LINK, buildInfo.agbUrl)
			impressum = impressum.replace(REPLACE_STRING_APP_IDENTIFIER, buildInfo.appIdentifier)
			impressum
		} catch (e: IOException) {
			e.printStackTrace()
			""
		}
	}

	private fun getFolderNameDisclaimer(context: Context): String {
		return FOLDER_NAME_DISCLAIMER + context.getString(R.string.language_key) + "/"
	}

	private fun getDefaultLanguageFolderNameDisclaimer(): String {
		return "$FOLDER_NAME_DISCLAIMER$DISCLAIMER_FALLBACK_LANGUAGE/"
	}

	fun getTermsOfUse(context: Context): String {
		var htmlString = loadHtml(
			context,
			getFolderNameDisclaimer(context) + FILE_NAME_TERMS_OF_USE
		)
		if (htmlString == null) htmlString = loadHtml(
			context,
			getDefaultLanguageFolderNameDisclaimer() + FILE_NAME_TERMS_OF_USE
		)
		if (htmlString == null) htmlString = ""
		return replaceUlTags(htmlString)
	}

	fun getDataProtection(context: Context): String {
		var htmlString = loadHtml(
			context,
			getFolderNameDisclaimer(context) + FILE_NAME_DATA_PROTECTION_STATEMENT
		)
		if (htmlString == null) htmlString = loadHtml(
			context,
			getDefaultLanguageFolderNameDisclaimer() + FILE_NAME_DATA_PROTECTION_STATEMENT
		)
		if (htmlString == null) htmlString = ""
		return replaceUlTags(htmlString)
	}

	private fun replaceUlTags(htmlString: String): String {
		return htmlString.replace("<ul>", "<myul>").replace("</ul>", "</myul>").replace("<li>", "<myli>")
			.replace("</li>", "</myli>")
	}

	private fun loadHtml(context: Context, path: String): String? {
		return try {
			val html = StringBuilder()
			BufferedReader(InputStreamReader(context.assets.open(path))).use { reader ->
				var line: String?
				while (reader.readLine().also { line = it } != null) {
					html.append(line)
				}
			}
			html.toString()
		} catch (e: IOException) {
			e.printStackTrace()
			null
		}
	}

}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/util/CutOutEdgeTreatment.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.util

import com.google.android.material.shape.EdgeTreatment
import com.google.android.material.shape.ShapePath
import kotlin.math.atan
import kotlin.math.sqrt

class CutOutEdgeTreatment(
	private val radius: Float,
	private val positionPercentage: Float
) : EdgeTreatment() {

	override fun getEdgePath(length: Float, center: Float, interpolation: Float, shapePath: ShapePath) {
		val cutOutCenter = length * positionPercentage

		// Calculate the vertical offset of the cut out. When interpolating the edge, the offset is the perpendicular distance
		// from the cut out center to the edge. When fully interpolated (1.0), the offset will be zero, while at zero interpolation
		// the offset will be equal to the radius
		val verticalOffset = (1.0f - interpolation) * radius
		val verticalOffsetRatio = verticalOffset / radius
		if (verticalOffsetRatio >= 1.0f) {
			// The vertical offset is so high that there would be no cut out drawn in the edge, so just draw a straight line along the edge
			shapePath.lineTo(length, 0.0f)
			return
		}

		// Calculate the X distance between the center and edge of the cut out, taking the interpolation value into consideration
		// When fully interpolated (1.0) the radiusX is the same as the radius
		val squaredRadius = radius * radius
		val verticalOffsetSquared = verticalOffset * verticalOffset
		val radiusX = sqrt((squaredRadius - verticalOffsetSquared).toDouble()).toFloat()

		// Draw a line from the start of the edge to the start of the cut out
		val cutOutStartX = cutOutCenter - radiusX
		shapePath.lineTo(cutOutStartX, 0.0f)

		// Calculate the arc of the cut out
		val cornerRadiusArcLength = Math.toDegrees(atan((radiusX / verticalOffset).toDouble())).toFloat()
		val cutoutArcOffset = 90.0f - cornerRadiusArcLength

		// Draw the cut out arc
		shapePath.addArc(
			cutOutCenter - radius,
			-radius - verticalOffset,
			cutOutCenter + radius,
			radius - verticalOffset,
			180.0f - cutoutArcOffset,
			cutoutArcOffset * 2.0f - 180.0f
		)

		// Draw a line from the end of the cut out to the end of the edge
		shapePath.lineTo(length, 0.0f)
	}


}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/util/EnvironmentUtil.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.util

import ch.admin.bag.covidcertificate.common.BuildConfig
import ch.admin.bag.covidcertificate.sdk.android.SdkEnvironment

object EnvironmentUtil {

	fun getSdkEnvironment(flavor: String = BuildConfig.FLAVOR) = when (flavor) {
		"dev" -> SdkEnvironment.DEV
		"abn" -> SdkEnvironment.ABN
		"prod" -> SdkEnvironment.PROD
		else -> throw IllegalArgumentException("Unknown environment $flavor")
	}

}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/util/ErrorCodeUtil.kt
================================================
package ch.admin.bag.covidcertificate.common.util

import ch.admin.bag.covidcertificate.sdk.core.models.state.CheckNationalRulesState
import ch.admin.bag.covidcertificate.sdk.core.models.state.CheckRevocationState
import ch.admin.bag.covidcertificate.sdk.core.models.state.CheckSignatureState
import ch.admin.bag.covidcertificate.sdk.core.models.state.VerificationState

fun VerificationState.getInvalidErrorCode(errorDelimiter: String = ", ", showNationalErrors: Boolean = false): String {
	val errorCodes = mutableListOf<String>()
	if (this !is VerificationState.INVALID) return ""

	val signatureState = signatureState
	if (signatureState is CheckSignatureState.INVALID) {
		errorCodes.add(signatureState.signatureErrorCode)
	}

	val revocationState = revocationState
	if (revocationState is CheckRevocationState.INVALID) {
		errorCodes.add(revocationState.revocationErrorCode)
	}

	val nationalRulesState = nationalRulesState
	if (showNationalErrors && nationalRulesState is CheckNationalRulesState.INVALID) {
		nationalRulesState.nationalRulesError?.errorCode?.let { errorCodes.add(it) }
	}
	return errorCodes.joinToString(errorDelimiter)
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/util/ErrorHelper.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.util

import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.graphics.Paint
import android.net.Uri
import android.provider.Settings
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.core.content.ContextCompat
import ch.admin.bag.covidcertificate.common.R

object ErrorHelper {
	@JvmOverloads
	fun updateErrorView(
		errorView: View,
		errorState: ErrorState,
		customButtonClickAction: Runnable?,
		context: Context?,
		showButton: Boolean = true
	) {
		errorView.findViewById<TextView>(R.id.error_status_title).setText(errorState.titleResId)
		errorView.findViewById<TextView>(R.id.error_status_text).setText(errorState.textResId)
		errorView.findViewById<ImageView>(R.id.error_status_image)
			.setImageDrawable(ContextCompat.getDrawable(errorView.context, errorState.imageResId))

		val buttonView = errorView.findViewById<TextView>(R.id.error_status_button)
		if (showButton) {
			buttonView.visibility = View.VISIBLE
			buttonView.setText(errorState.actionResId)
			buttonView.paintFlags = buttonView.paintFlags or Paint.UNDERLINE_TEXT_FLAG
			buttonView.setOnClickListener { executeErrorAction(errorState, customButtonClickAction, context) }
		} else {
			buttonView.visibility = View.GONE
		}
	}

	private fun executeErrorAction(errorState: ErrorState, customButtonClickAction: Runnable?, context: Context?) {
		customButtonClickAction?.run()
		when (errorState) {
			ErrorState.CAMERA_ACCESS_DENIED -> openApplicationSettings(context)
			else -> {}
		}
	}

	private fun openApplicationSettings(context: Context?) {
		val context = context ?: return
		val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
		val uri = Uri.fromParts("package", context.packageName, null)
		intent.data = uri
		try {
			context.startActivity(intent)
		} catch (e: ActivityNotFoundException) {
			Toast.makeText(context, "Could not open settings", Toast.LENGTH_LONG).show()
		}
	}
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/util/ErrorState.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.util

import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import ch.admin.bag.covidcertificate.common.R

enum class ErrorState(
	@field:StringRes @param:StringRes val titleResId: Int,
	@field:StringRes @param:StringRes val textResId: Int,
	@field:StringRes @param:StringRes val actionResId: Int,
	@field:DrawableRes @param:DrawableRes val imageResId: Int
) {
	NETWORK(
		R.string.error_network_title,
		R.string.error_network_text,
		R.string.error_action_retry,
		R.drawable.ic_error_triangle
	),
	CAMERA_ACCESS_DENIED(
		R.string.error_camera_permission_title,
		R.string.error_camera_permission_text,
		R.string.error_action_change_settings,
		R.drawable.ic_cam_off
	),
	NO_VALID_QR_CODE(
		R.string.error_title,
		R.string.qr_scanner_error,
		R.string.ok_button,
		R.drawable.ic_error_triangle
	);
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/util/HorizontalMarginItemDecoration.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.util

import android.content.Context
import android.graphics.Rect
import android.view.View
import androidx.recyclerview.widget.RecyclerView

class HorizontalMarginItemDecoration(context: Context, val horizontalMarginInPx: Int) :
		RecyclerView.ItemDecoration() {

		override fun getItemOffsets(
			outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State
		) {
			outRect.right = horizontalMarginInPx
			outRect.left = horizontalMarginInPx
		}

	}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/util/LocaleUtil.kt
================================================
package ch.admin.bag.covidcertificate.common.util

import android.content.Context
import android.content.res.Configuration
import ch.admin.bag.covidcertificate.common.R
import java.util.*

object LocaleUtil {

	const val DEFAULT_COUNTRY = "CH"

	fun isSystemLangNotEnglish(context: Context): Boolean {
		return context.getString(R.string.language_key) != "en"
	}

	fun updateLanguage(context: Context, language: String?): Context {
		if (!language.isNullOrEmpty()) {
			val config = Configuration()
			config.setLocale(Locale(language, DEFAULT_COUNTRY))
			return context.createConfigurationContext(config)
		}
		return context
	}

}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/util/SingleLiveEvent.java
================================================
/*
 *  Copyright 2017 Google Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package ch.admin.bag.covidcertificate.common.util;

import android.util.Log;
import androidx.annotation.MainThread;
import androidx.annotation.Nullable;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;

import java.util.concurrent.atomic.AtomicBoolean;

/**
 * A lifecycle-aware observable that sends only new updates after subscription, used for events like
 * navigation and Snackbar messages.
 * <p>
 * This avoids a common problem with events: on configuration change (like rotation) an update
 * can be emitted if the observer is active. This LiveData only calls the observable if there's an
 * explicit call to setValue() or call().
 * <p>
 * Note that only one observer is going to be notified of changes.
 */
public class SingleLiveEvent<T> extends MutableLiveData<T> {

	private static final String TAG = "SingleLiveEvent";

	private final AtomicBoolean mPending = new AtomicBoolean(false);

	@MainThread
	public void observe(LifecycleOwner owner, final Observer<? super T> observer) {

		if (hasActiveObservers()) {
			Log.w(TAG, "Multiple observers registered but only one will be notified of changes.");
		}

		// Observe the internal MutableLiveData
		super.observe(owner, new Observer<T>() {
			@Override
			public void onChanged(@Nullable T t) {
				if (mPending.compareAndSet(true, false)) {
					observer.onChanged(t);
				}
			}
		});
	}

	@MainThread
	public void setValue(@Nullable T t) {
		mPending.set(true);
		super.setValue(t);
	}

	/**
	 * Used for cases where T is Void, to make calls cleaner.
	 */
	@MainThread
	public void call() {
		setValue(null);
	}
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/util/StringUtil.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.util

import android.graphics.Typeface
import android.text.SpannableString
import android.text.style.StyleSpan
import ch.admin.bag.covidcertificate.sdk.android.extensions.DEFAULT_DISPLAY_DATE_FORMATTER
import ch.admin.bag.covidcertificate.sdk.android.extensions.DEFAULT_DISPLAY_DATE_TIME_FORMATTER
import java.time.LocalDateTime

fun String.makeBold(): SpannableString = SpannableString(this).apply {
	setSpan(StyleSpan(Typeface.BOLD), 0, this@makeBold.length, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE)
}

fun String.makeSubStringBold(
	subString: String,
	startIndex: Int = 0,
	ignoreCase: Boolean = true
): SpannableString =
	SpannableString(this).apply {
		val indexSubString = this@makeSubStringBold.indexOf(subString, startIndex, ignoreCase)
		if (indexSubString >= 0) {
			setSpan(
				StyleSpan(Typeface.BOLD),
				indexSubString,
				indexSubString + subString.length,
				SpannableString.SPAN_INCLUSIVE_EXCLUSIVE
			)
		}
	}

fun String.makeSubStringsBold(
	subStrings: List<String>,
	startIndex: Int = 0,
	ignoreCase: Boolean = true
): SpannableString = SpannableString(this).apply {
	subStrings.forEach {
		val indexSubString = this@makeSubStringsBold.indexOf(it, startIndex, ignoreCase)
		if (indexSubString >= 0) {
			setSpan(
				StyleSpan(Typeface.BOLD),
				indexSubString,
				indexSubString + it.length,
				SpannableString.SPAN_INCLUSIVE_EXCLUSIVE
			)
		}
	}
}

fun String.addBoldDate(dateReplacementString: String, date: LocalDateTime): SpannableString {
	val dateString = date.format(DEFAULT_DISPLAY_DATE_FORMATTER)
	return SpannableString(this.replace(dateReplacementString, dateString)).apply {
		val indexSubString = this.indexOf(dateString)
		if (indexSubString >= 0) {
			setSpan(
				StyleSpan(Typeface.BOLD),
				indexSubString,
				indexSubString + dateString.length,
				SpannableString.SPAN_INCLUSIVE_EXCLUSIVE
			)
		}
	}
}

fun String.addBoldDateTime(dateTimeReplacementString: String, dateTime: LocalDateTime): SpannableString {
	val dateTimeString = dateTime.format(DEFAULT_DISPLAY_DATE_TIME_FORMATTER)
	return SpannableString(this.replace(dateTimeReplacementString, dateTimeString)).apply {
		val indexSubString = this.indexOf(dateTimeString)
		if (indexSubString >= 0) {
			setSpan(
				StyleSpan(Typeface.BOLD),
				indexSubString,
				indexSubString + dateTimeString.length,
				SpannableString.SPAN_INCLUSIVE_EXCLUSIVE
			)
		}
	}
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/util/UiUtil.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.util

import android.view.Window
import android.view.WindowManager

private val allowlistedFlavours = listOf("abn", "dev")

fun Window.setSecureFlagToBlockScreenshots(flavor: String) {
	if (!allowlistedFlavours.contains(flavor)) {
		setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
	}
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/util/UlTagHandler.java
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.util;

import android.text.Editable;
import android.text.Html;
import android.text.Spanned;
import android.text.style.BulletSpan;

import org.xml.sax.XMLReader;

public class UlTagHandler implements Html.TagHandler {
	private static final int indent = 30;
	public static String LI = "myli";


	@Override
	public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {
	if (tag.equals(LI)) {
			if (opening) {
				if (output.length() > 0 && output.charAt(output.length() - 1) != '\n') {
					output.append("\n");
				}
				start(output, new Ul());
			} else {
				if (output.charAt(output.length() - 1) != '\n') {
					output.append("\n");
				}
				BulletSpan newBullet = new BulletSpan(indent);
				end(output, Ul.class, newBullet);
			}
		}
	}

	private static void start(Editable text, Object mark) {
		int len = text.length();
		text.setSpan(mark, len, len, Spanned.SPAN_MARK_MARK);
	}

	private static void end(Editable text, Class<?> kind, Object... replaces) {
		int len = text.length();
		Object obj = getLast(text, kind);
		int where = text.getSpanStart(obj);
		text.removeSpan(obj);
		if (where != len) {
			for (Object replace : replaces) {
				text.setSpan(replace, where, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
			}
		}
	}

	private static Object getLast(Spanned text, Class<?> kind) {
		Object[] objs = text.getSpans(0, text.length(), kind);
		if (objs.length == 0) {
			return null;
		}
		return objs[objs.length - 1];
	}

	private static class Ul { }

}


================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/util/UrlUtil.java
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.util;

import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.widget.Toast;

public class UrlUtil {

	public static void openUrl(Context context, String url) {
		Intent intent = new Intent(Intent.ACTION_VIEW);
		intent.setData(Uri.parse(url));
		try {
			context.startActivity(intent);
		} catch (ActivityNotFoundException e) {
			Toast.makeText(context, "No browser installed", Toast.LENGTH_LONG).show();
		}
	}

}


================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/views/MarginItemDecoration.kt
================================================
package ch.admin.bag.covidcertificate.common.views

import android.content.Context
import android.graphics.Rect
import android.view.View
import androidx.annotation.DimenRes
import androidx.recyclerview.widget.RecyclerView

class VerticalMarginItemDecoration(context: Context, @DimenRes marginRes: Int) : RecyclerView.ItemDecoration() {

	private val marginPx = context.resources.getDimensionPixelSize(marginRes)

	override fun getItemOffsets(
		outRect: Rect, view: View,
		parent: RecyclerView,
		state: RecyclerView.State
	) {
		with(outRect) {
			if (parent.getChildAdapterPosition(view) != 0) {
				top = marginPx
			}
		}
	}
}

================================================
FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/views/ViewExtensions.kt
================================================
/*
 * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * SPDX-License-Identifier: MPL-2.0
 */

package ch.admin.bag.covidcertificate.common.views

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.content.res.ColorStateList
import android.view.View
import android.view.animation.AccelerateDecelerateInterpolator
import android.view.animation.AccelerateInterpolator
import android.view.animation.DecelerateInterpolator
import androidx.annotation.ColorInt
import androidx.core.content.ContextCompat
import ch.admin.bag.covidcertificate.common.R
import ch.admin.bag.covidcertificate.common.util.CutOutEdgeTreatment
import com.google.android.material.shape.MaterialShapeDrawable
import com.google.android.material.shape.ShapeAppearanceModel

fun View.showAnimated(
	duration: Long = resources.getInteger(android.R.integer.config_shortAnimTime).toLong(),
	fade: Boolean = true
) {
	animation?.cancel()
	if (visibility == View.VISIBLE) return

	visibility = View.VISIBLE
	alpha = if (fade) 0f else 1f

	animate()
		.setDuration(duration)
		.alpha(1f)
		.setInterpolator(DecelerateInterpolator())
		.setListener(null)
Download .txt
gitextract_e7z7c8gy/

├── .github/
│   ├── actions/
│   │   └── gradle_docker/
│   │       ├── action.yml
│   │       └── main.sh
│   └── workflows/
│       ├── appcenter_verifier_abn.yml
│       ├── appcenter_verifier_dev.yml
│       ├── appcenter_verifier_prod.yml
│       ├── appcenter_verifier_prodfdroid.yml
│       ├── appcenter_wallet_abn.yml
│       ├── appcenter_wallet_dev.yml
│       ├── appcenter_wallet_prod.yml
│       ├── appcenter_wallet_prodfdroid.yml
│       ├── browserstack_wallet_abn.yml
│       ├── build.yml
│       └── gradle-wrapper-validation.yml
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── REPRODUCIBLE_BUILDS.md
├── apkdiff.py
├── build.gradle
├── buildAndCompare.sh
├── common/
│   ├── .gitignore
│   ├── build.gradle
│   ├── consumer-rules.pro
│   ├── proguard-rules.pro
│   └── src/
│       ├── abn/
│       │   └── java/
│       │       └── ch/
│       │           └── admin/
│       │               └── bag/
│       │                   └── covidcertificate/
│       │                       └── common/
│       │                           └── debug/
│       │                               └── DebugFragment.kt
│       ├── dev/
│       │   ├── java/
│       │   │   └── ch/
│       │   │       └── admin/
│       │   │           └── bag/
│       │   │               └── covidcertificate/
│       │   │                   └── common/
│       │   │                       └── debug/
│       │   │                           ├── DebugFragment.kt
│       │   │                           └── DebugSecureStorage.kt
│       │   └── res/
│       │       └── xml/
│       │           └── network_security_config.xml
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── assets/
│       │   │   └── impressum/
│       │   │       ├── de/
│       │   │       │   ├── impressum.html
│       │   │       │   └── licence.html
│       │   │       ├── en/
│       │   │       │   ├── impressum.html
│       │   │       │   └── licence.html
│       │   │       ├── fonts/
│       │   │       │   ├── Inter-Bold.otf
│       │   │       │   └── Inter-Light.otf
│       │   │       ├── fr/
│       │   │       │   ├── impressum.html
│       │   │       │   └── licence.html
│       │   │       ├── it/
│       │   │       │   ├── impressum.html
│       │   │       │   └── licence.html
│       │   │       └── rm/
│       │   │           ├── impressum.html
│       │   │           └── licence.html
│       │   ├── java/
│       │   │   └── ch/
│       │   │       └── admin/
│       │   │           └── bag/
│       │   │               └── covidcertificate/
│       │   │                   └── common/
│       │   │                       ├── BaseActivity.kt
│       │   │                       ├── browserstack/
│       │   │                       │   ├── AirplaneMode.kt
│       │   │                       │   ├── BadNetwork.kt
│       │   │                       │   ├── Normal.kt
│       │   │                       │   └── Onboarding.kt
│       │   │                       ├── config/
│       │   │                       │   ├── CertificateRenewalInfoDetailModel.kt
│       │   │                       │   ├── CertificateRenewalInfoModel.kt
│       │   │                       │   ├── CertificateRenewalType.kt
│       │   │                       │   ├── CheckModesInfosModel.kt
│       │   │                       │   ├── ConfigModel.kt
│       │   │                       │   ├── ConfigViewModel.kt
│       │   │                       │   ├── CovidCertificateNewsItem.kt
│       │   │                       │   ├── EolBannerInfoModel.kt
│       │   │                       │   ├── FaqEntryModel.kt
│       │   │                       │   ├── FaqIntroSection.kt
│       │   │                       │   ├── FaqModel.kt
│       │   │                       │   ├── ForeignRulesHintModel.kt
│       │   │                       │   ├── InfoBoxModel.kt
│       │   │                       │   ├── InfoCovidCertificateNews.kt
│       │   │                       │   ├── RefreshButtonInfoModel.kt
│       │   │                       │   ├── VaccinationBookingInfoModel.kt
│       │   │                       │   └── VaccinationHintModel.kt
│       │   │                       ├── data/
│       │   │                       │   └── ConfigSecureStorage.kt
│       │   │                       ├── dialog/
│       │   │                       │   └── InfoDialogFragment.kt
│       │   │                       ├── exception/
│       │   │                       │   ├── HttpIOException.kt
│       │   │                       │   └── TimeDeviationException.kt
│       │   │                       ├── extensions/
│       │   │                       │   ├── ContextExtensions.kt
│       │   │                       │   ├── DccCertExtensions.kt
│       │   │                       │   ├── LifecycleOwnerExtensions.kt
│       │   │                       │   ├── OkHttpExtensions.kt
│       │   │                       │   └── WindowExtensions.kt
│       │   │                       ├── faq/
│       │   │                       │   ├── FaqAdapter.kt
│       │   │                       │   ├── FaqFragment.kt
│       │   │                       │   ├── FaqItem.kt
│       │   │                       │   ├── FaqViewHolder.kt
│       │   │                       │   └── model/
│       │   │                       │       └── Header.kt
│       │   │                       ├── html/
│       │   │                       │   ├── BuildInfo.kt
│       │   │                       │   └── ImprintFragment.kt
│       │   │                       ├── net/
│       │   │                       │   ├── ConfigRepository.kt
│       │   │                       │   └── ConfigService.kt
│       │   │                       ├── onboarding/
│       │   │                       │   ├── BaseOnboardingActivity.kt
│       │   │                       │   └── SimpleOnboardingPagerAdapter.kt
│       │   │                       ├── qr/
│       │   │                       │   ├── CameraPermissionExplanationDialog.kt
│       │   │                       │   ├── KittlerBinarizer.kt
│       │   │                       │   ├── QRCodeReaderHelper.kt
│       │   │                       │   ├── QrScanFragment.kt
│       │   │                       │   └── QrScannerState.kt
│       │   │                       ├── settings/
│       │   │                       │   └── SettingsFragment.kt
│       │   │                       ├── util/
│       │   │                       │   ├── AssetUtil.kt
│       │   │                       │   ├── CutOutEdgeTreatment.kt
│       │   │                       │   ├── EnvironmentUtil.kt
│       │   │                       │   ├── ErrorCodeUtil.kt
│       │   │                       │   ├── ErrorHelper.kt
│       │   │                       │   ├── ErrorState.kt
│       │   │                       │   ├── HorizontalMarginItemDecoration.kt
│       │   │                       │   ├── LocaleUtil.kt
│       │   │                       │   ├── SingleLiveEvent.java
│       │   │                       │   ├── StringUtil.kt
│       │   │                       │   ├── UiUtil.kt
│       │   │                       │   ├── UlTagHandler.java
│       │   │                       │   └── UrlUtil.java
│       │   │                       └── views/
│       │   │                           ├── MarginItemDecoration.kt
│       │   │                           ├── ViewExtensions.kt
│       │   │                           └── WindowInsetsLayout.kt
│       │   └── res/
│       │       ├── anim/
│       │       │   ├── fragment_open_enter.xml
│       │       │   ├── fragment_open_exit.xml
│       │       │   ├── slide_enter.xml
│       │       │   ├── slide_exit.xml
│       │       │   ├── slide_pop_enter.xml
│       │       │   └── slide_pop_exit.xml
│       │       ├── color/
│       │       │   ├── selector_black_or_white.xml
│       │       │   ├── selector_blue_or_white.xml
│       │       │   ├── selector_grey_or_blue.xml
│       │       │   ├── selector_grey_or_white.xml
│       │       │   ├── selector_transparent_or_blue.xml
│       │       │   ├── selector_white_or_black.xml
│       │       │   ├── selector_white_or_blue.xml
│       │       │   └── text_radio_checkable.xml
│       │       ├── drawable/
│       │       │   ├── bg_button_default.xml
│       │       │   ├── bg_button_red.xml
│       │       │   ├── bg_button_white.xml
│       │       │   ├── bg_corners_top_left.xml
│       │       │   ├── bg_dialog.xml
│       │       │   ├── bg_pill.xml
│       │       │   ├── bg_rect_rounded_sheet.xml
│       │       │   ├── bg_rect_rounded_small.xml
│       │       │   ├── bg_rect_rounded_small_blue_ripple.xml
│       │       │   ├── bg_rect_rounded_small_checkable.xml
│       │       │   ├── bg_rect_rounded_small_red.xml
│       │       │   ├── btn_radio_checkable.xml
│       │       │   ├── dot_black.xml
│       │       │   ├── dot_grey.xml
│       │       │   ├── dot_white.xml
│       │       │   ├── header_bottom.xml
│       │       │   ├── header_collapsed_shadow.xml
│       │       │   ├── ic_1g.xml
│       │       │   ├── ic_2g.xml
│       │       │   ├── ic_2g_green.xml
│       │       │   ├── ic_2g_grey.xml
│       │       │   ├── ic_2g_plus.xml
│       │       │   ├── ic_3g.xml
│       │       │   ├── ic_arrow_contract.xml
│       │       │   ├── ic_arrow_expand.xml
│       │       │   ├── ic_arrow_forward.xml
│       │       │   ├── ic_bund_small.xml
│       │       │   ├── ic_bundwappen_big.xml
│       │       │   ├── ic_call.xml
│       │       │   ├── ic_cam_off.xml
│       │       │   ├── ic_camera_switch.xml
│       │       │   ├── ic_check_filled.xml
│       │       │   ├── ic_check_green.xml
│       │       │   ├── ic_check_grey.xml
│       │       │   ├── ic_check_large.xml
│       │       │   ├── ic_checkbox_empty.xml
│       │       │   ├── ic_checkbox_filled.xml
│       │       │   ├── ic_close.xml
│       │       │   ├── ic_close_red.xml
│       │       │   ├── ic_dot.xml
│       │       │   ├── ic_double_check.xml
│       │       │   ├── ic_error.xml
│       │       │   ├── ic_error_blue.xml
│       │       │   ├── ic_error_grey.xml
│       │       │   ├── ic_error_large.xml
│       │       │   ├── ic_error_orange.xml
│       │       │   ├── ic_error_triangle.xml
│       │       │   ├── ic_expire_i.xml
│       │       │   ├── ic_faq.xml
│       │       │   ├── ic_header_slim.xml
│       │       │   ├── ic_how_it_works_image.xml
│       │       │   ├── ic_info.xml
│       │       │   ├── ic_info_alert.xml
│       │       │   ├── ic_info_blue.xml
│       │       │   ├── ic_info_outline.xml
│       │       │   ├── ic_invalid_grey.xml
│       │       │   ├── ic_invalid_red.xml
│       │       │   ├── ic_light_off.xml
│       │       │   ├── ic_light_off_blue.xml
│       │       │   ├── ic_light_on.xml
│       │       │   ├── ic_light_on_black.xml
│       │       │   ├── ic_link_external.xml
│       │       │   ├── ic_load.xml
│       │       │   ├── ic_no1g.xml
│       │       │   ├── ic_no2g.xml
│       │       │   ├── ic_no3g.xml
│       │       │   ├── ic_no_2_g_plus_height.xml
│       │       │   ├── ic_no_connection.xml
│       │       │   ├── ic_no_connection_large.xml
│       │       │   ├── ic_notification.xml
│       │       │   ├── ic_notification_filled.xml
│       │       │   ├── ic_offline.xml
│       │       │   ├── ic_offline_large.xml
│       │       │   ├── ic_offline_orange.xml
│       │       │   ├── ic_one.xml
│       │       │   ├── ic_phone.xml
│       │       │   ├── ic_plus.xml
│       │       │   ├── ic_plus_green.xml
│       │       │   ├── ic_privacy.xml
│       │       │   ├── ic_privacy_grey.xml
│       │       │   ├── ic_process_error.xml
│       │       │   ├── ic_process_error_grey.xml
│       │       │   ├── ic_process_error_large.xml
│       │       │   ├── ic_qr_certificate_light.xml
│       │       │   ├── ic_qr_certificate_light_no.xml
│       │       │   ├── ic_question_outline.xml
│       │       │   ├── ic_retry.xml
│       │       │   ├── ic_scanner_alert.xml
│       │       │   ├── ic_scanner_alert_white.xml
│       │       │   ├── ic_settings.xml
│       │       │   ├── ic_t.xml
│       │       │   ├── ic_three.xml
│       │       │   ├── ic_timeerror.xml
│       │       │   ├── ic_timeerror_large.xml
│       │       │   ├── ic_timeerror_orange.xml
│       │       │   ├── ic_timelapse.xml
│       │       │   ├── ic_timelapse_blue.xml
│       │       │   ├── ic_timelapse_red.xml
│       │       │   ├── ic_travel.xml
│       │       │   ├── ic_two.xml
│       │       │   ├── ic_zoom_off.xml
│       │       │   ├── ic_zoom_off_white.xml
│       │       │   ├── ic_zoom_on.xml
│       │       │   ├── ic_zoom_on_black.xml
│       │       │   ├── illu_onboarding_data_protection.xml
│       │       │   ├── line_dashed_grey.xml
│       │       │   ├── qr_scanner_bottom_left.xml
│       │       │   ├── qr_scanner_bottom_right.xml
│       │       │   ├── qr_scanner_top_left.xml
│       │       │   ├── qr_scanner_top_right.xml
│       │       │   ├── ripple_rect.xml
│       │       │   ├── ripple_rounded.xml
│       │       │   ├── ripple_rounded_button.xml
│       │       │   ├── ripple_rounded_rect.xml
│       │       │   ├── ripple_rounded_rect_banner.xml
│       │       │   ├── ripple_rounded_rect_small.xml
│       │       │   ├── tab_selector.xml
│       │       │   └── tab_selector_white.xml
│       │       ├── font/
│       │       │   └── inter.xml
│       │       ├── layout/
│       │       │   ├── activity_onboarding.xml
│       │       │   ├── dialog_camera_permission_explanation.xml
│       │       │   ├── dialog_fragment_info_box.xml
│       │       │   ├── fragment_debug.xml
│       │       │   ├── fragment_faq.xml
│       │       │   ├── fragment_html.xml
│       │       │   ├── fragment_settings.xml
│       │       │   ├── item_error_status.xml
│       │       │   ├── item_faq_header.xml
│       │       │   ├── item_faq_intro_section.xml
│       │       │   ├── item_faq_question.xml
│       │       │   ├── item_header.xml
│       │       │   └── item_language_option.xml
│       │       ├── menu/
│       │       │   └── imprint.xml
│       │       ├── values/
│       │       │   ├── attrs.xml
│       │       │   ├── colors.xml
│       │       │   ├── dimens.xml
│       │       │   ├── strings.xml
│       │       │   └── styles.xml
│       │       ├── values-de/
│       │       │   └── strings.xml
│       │       ├── values-fr/
│       │       │   └── strings.xml
│       │       ├── values-it/
│       │       │   └── strings.xml
│       │       ├── values-rm/
│       │       │   └── strings.xml
│       │       └── xml/
│       │           └── network_security_config.xml
│       └── prod/
│           └── java/
│               └── ch/
│                   └── admin/
│                       └── bag/
│                           └── covidcertificate/
│                               └── common/
│                                   └── debug/
│                                       └── DebugFragment.kt
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── loadConfigs.sh
├── settings.gradle
├── verifier/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   ├── src/
│   │   ├── abn/
│   │   │   └── assets/
│   │   │       └── faq/
│   │   │           └── config.json
│   │   ├── dev/
│   │   │   └── assets/
│   │   │       └── faq/
│   │   │           └── config.json
│   │   └── main/
│   │       ├── AndroidManifest.xml
│   │       ├── assets/
│   │       │   └── faq/
│   │       │       └── config.json
│   │       ├── java/
│   │       │   └── ch/
│   │       │       └── admin/
│   │       │           └── bag/
│   │       │               └── covidcertificate/
│   │       │                   └── verifier/
│   │       │                       ├── HomeFragment.kt
│   │       │                       ├── MainActivity.kt
│   │       │                       ├── MainApplication.kt
│   │       │                       ├── data/
│   │       │                       │   └── VerifierSecureStorage.kt
│   │       │                       ├── extensions/
│   │       │                       │   └── ContextExtensions.kt
│   │       │                       ├── faq/
│   │       │                       │   └── VerifierFaqFragment.kt
│   │       │                       ├── modes/
│   │       │                       │   ├── ChooseModeDialogFragment.kt
│   │       │                       │   └── ModesAndConfigViewModel.kt
│   │       │                       ├── news/
│   │       │                       │   └── InfoCertificateNewsFragment.kt
│   │       │                       ├── pager/
│   │       │                       │   ├── HomescreenPageAdapter.kt
│   │       │                       │   └── HomescreenPagerFragment.kt
│   │       │                       ├── qr/
│   │       │                       │   └── VerifierQrScanFragment.kt
│   │       │                       ├── updateboarding/
│   │       │                       │   ├── UpdateboardingActivity.kt
│   │       │                       │   ├── UpdateboardingAgbFragment.kt
│   │       │                       │   └── UpdateboardingCertificateLightFragment.kt
│   │       │                       ├── verification/
│   │       │                       │   ├── VerificationAdapter.kt
│   │       │                       │   ├── VerificationFragment.kt
│   │       │                       │   ├── VerificationItem.kt
│   │       │                       │   ├── VerificationStateUtil.kt
│   │       │                       │   ├── VerificationViewHolder.kt
│   │       │                       │   └── VerificationViewModel.kt
│   │       │                       └── zebra/
│   │       │                           ├── ZebraActionBroadcastReceiver.kt
│   │       │                           ├── ZebraDataWedgeApiUtil.kt
│   │       │                           └── ZebraResultActionBroadcastReceiver.kt
│   │       ├── play/
│   │       │   ├── listings/
│   │       │   │   ├── de-DE/
│   │       │   │   │   ├── full-description.txt
│   │       │   │   │   ├── short-description.txt
│   │       │   │   │   └── title.txt
│   │       │   │   ├── en-US/
│   │       │   │   │   ├── full-description.txt
│   │       │   │   │   ├── short-description.txt
│   │       │   │   │   └── title.txt
│   │       │   │   ├── fr-FR/
│   │       │   │   │   ├── full-description.txt
│   │       │   │   │   ├── short-description.txt
│   │       │   │   │   └── title.txt
│   │       │   │   └── it-IT/
│   │       │   │       ├── full-description.txt
│   │       │   │       ├── short-description.txt
│   │       │   │       └── title.txt
│   │       │   └── release-notes/
│   │       │       └── en-US/
│   │       │           └── default.txt
│   │       └── res/
│   │           ├── drawable/
│   │           │   ├── bg_bubble_bottom_left.xml
│   │           │   ├── ic_faq_image.xml
│   │           │   ├── ic_header_2g_off.xml
│   │           │   ├── ic_header_2g_on.xml
│   │           │   ├── ic_header_plus_off.xml
│   │           │   ├── ic_header_plus_on.xml
│   │           │   ├── ic_illu_home_1.xml
│   │           │   ├── ic_illu_home_2.xml
│   │           │   ├── ic_launcher_background.xml
│   │           │   ├── ic_settings.xml
│   │           │   └── illu_updateboarding_certificate_light.xml
│   │           ├── layout/
│   │           │   ├── activity_main.xml
│   │           │   ├── dialog_fragment_choose_mode.xml
│   │           │   ├── dialog_fragment_info_certificate_news.xml
│   │           │   ├── fragment_home.xml
│   │           │   ├── fragment_home_screen_pager.xml
│   │           │   ├── fragment_qr_scan.xml
│   │           │   ├── fragment_updateboarding_agb.xml
│   │           │   ├── fragment_updateboarding_certificate_light.xml
│   │           │   ├── fragment_verification.xml
│   │           │   ├── item_certificate_news.xml
│   │           │   ├── item_mode_button.xml
│   │           │   ├── item_mode_info.xml
│   │           │   ├── item_progress_indicator.xml
│   │           │   ├── item_verification_header_icon.xml
│   │           │   ├── item_verification_status.xml
│   │           │   └── item_verification_status_info.xml
│   │           └── mipmap-anydpi-v26/
│   │               ├── ic_launcher.xml
│   │               └── ic_launcher_round.xml
│   └── testKeystore
└── wallet/
    ├── .gitignore
    ├── build.gradle
    ├── proguard-rules.pro
    ├── src/
    │   ├── abn/
    │   │   ├── assets/
    │   │   │   └── faq/
    │   │   │       └── config.json
    │   │   └── java/
    │   │       └── ch/
    │   │           └── admin/
    │   │               └── bag/
    │   │                   └── covidcertificate/
    │   │                       └── wallet/
    │   │                           └── debug/
    │   │                               └── WalletDebugFragment.kt
    │   ├── androidTest/
    │   │   └── java/
    │   │       └── ch/
    │   │           └── admin/
    │   │               └── bag/
    │   │                   └── covidcertificate/
    │   │                       └── wallet/
    │   │                           ├── EspressoUtil.kt
    │   │                           ├── LoadconfigTest.kt
    │   │                           ├── NestedScrollViewScrollTo.kt
    │   │                           ├── OnboardingTest.kt
    │   │                           ├── RecyclerViewNotEmptyAssertion.kt
    │   │                           ├── ScanCountTest.kt
    │   │                           ├── TransferCodeTest.kt
    │   │                           └── WaitUntilVisibleAction.kt
    │   ├── dev/
    │   │   ├── assets/
    │   │   │   └── faq/
    │   │   │       └── config.json
    │   │   └── java/
    │   │       └── ch/
    │   │           └── admin/
    │   │               └── bag/
    │   │                   └── covidcertificate/
    │   │                       └── wallet/
    │   │                           └── debug/
    │   │                               ├── DebugCertificateItem.kt
    │   │                               ├── DebugCertificatesListAdapter.kt
    │   │                               ├── DebugCertificatesListViewHolder.kt
    │   │                               └── WalletDebugFragment.kt
    │   ├── main/
    │   │   ├── AndroidManifest.xml
    │   │   ├── assets/
    │   │   │   └── faq/
    │   │   │       └── config.json
    │   │   ├── java/
    │   │   │   └── ch/
    │   │   │       └── admin/
    │   │   │           └── bag/
    │   │   │               └── covidcertificate/
    │   │   │                   └── wallet/
    │   │   │                       ├── CertificatesAndConfigViewModel.kt
    │   │   │                       ├── DeeplinkViewModel.kt
    │   │   │                       ├── MainActivity.kt
    │   │   │                       ├── MainApplication.kt
    │   │   │                       ├── add/
    │   │   │                       │   └── CertificateAddFragment.kt
    │   │   │                       ├── data/
    │   │   │                       │   ├── CertificateStorage.kt
    │   │   │                       │   ├── WalletDataItem.kt
    │   │   │                       │   ├── WalletDataSecureStorage.kt
    │   │   │                       │   ├── WalletSecureStorage.kt
    │   │   │                       │   └── adapter/
    │   │   │                       │       └── InstantJsonAdapter.kt
    │   │   │                       ├── detail/
    │   │   │                       │   ├── CertificateDetailAdapter.kt
    │   │   │                       │   ├── CertificateDetailFragment.kt
    │   │   │                       │   ├── CertificateDetailItem.kt
    │   │   │                       │   ├── CertificateDetailItemListBuilder.kt
    │   │   │                       │   └── CertificateDetailViewHolder.kt
    │   │   │                       ├── dialog/
    │   │   │                       │   ├── CertificateBannerInfoDialogFragment.kt
    │   │   │                       │   ├── ModeInfoDialogFragment.kt
    │   │   │                       │   └── RefreshButtonInfoDialogFragment.kt
    │   │   │                       ├── faq/
    │   │   │                       │   └── WalletFaqFragment.kt
    │   │   │                       ├── homescreen/
    │   │   │                       │   ├── HomeFragment.kt
    │   │   │                       │   └── pager/
    │   │   │                       │       ├── CertificatePagerFragment.kt
    │   │   │                       │       ├── CertificatesPagerAdapter.kt
    │   │   │                       │       ├── PagerDiffUtil.kt
    │   │   │                       │       ├── StatefulWalletItem.kt
    │   │   │                       │       ├── TransferCodePagerFragment.kt
    │   │   │                       │       └── WalletItem.kt
    │   │   │                       ├── howto/
    │   │   │                       │   └── HowToScanFragment.kt
    │   │   │                       ├── light/
    │   │   │                       │   ├── CertificateLightConversionFragment.kt
    │   │   │                       │   ├── CertificateLightDetailFragment.kt
    │   │   │                       │   ├── CertificateLightErrorCodes.kt
    │   │   │                       │   ├── CertificateLightPagerFragment.kt
    │   │   │                       │   ├── CertificateLightViewModel.kt
    │   │   │                       │   ├── model/
    │   │   │                       │   │   ├── CertificateLightConversionResponse.kt
    │   │   │                       │   │   └── CertificateLightConversionState.kt
    │   │   │                       │   └── net/
    │   │   │                       │       ├── CertificateLightRepository.kt
    │   │   │                       │       ├── CertificateLightRequestBody.kt
    │   │   │                       │       ├── CertificateLightResponse.kt
    │   │   │                       │       └── CertificateLightService.kt
    │   │   │                       ├── list/
    │   │   │                       │   ├── CertificatesListFragment.kt
    │   │   │                       │   ├── CertificatesListTouchHelper.kt
    │   │   │                       │   ├── WalletDataListAdapter.kt
    │   │   │                       │   ├── WalletDataListItem.kt
    │   │   │                       │   └── WalletDataListViewHolder.kt
    │   │   │                       ├── networking/
    │   │   │                       │   └── interceptor/
    │   │   │                       │       └── AcceptLanguageHeaderInterceptor.kt
    │   │   │                       ├── onboarding/
    │   │   │                       │   ├── OnboardingActivity.kt
    │   │   │                       │   ├── OnboardingAgbFragment.kt
    │   │   │                       │   ├── OnboardingContentFragment.kt
    │   │   │                       │   ├── OnboardingIntroFragment.kt
    │   │   │                       │   ├── OnboardingPreInfoFragment.kt
    │   │   │                       │   ├── agbupdate/
    │   │   │                       │   │   └── UpdateboardingAgbFragment.kt
    │   │   │                       │   ├── certificatelight/
    │   │   │                       │   │   └── UpdateboardingCertificateLightFragment.kt
    │   │   │                       │   └── validity/
    │   │   │                       │       ├── UpdateboardingValidity1Fragment.kt
    │   │   │                       │       ├── UpdateboardingValidity2Fragment.kt
    │   │   │                       │       ├── UpdateboardingValidity3Fragment.kt
    │   │   │                       │       └── UpdateboardingValidity4Fragment.kt
    │   │   │                       ├── pdf/
    │   │   │                       │   ├── PdfViewModel.kt
    │   │   │                       │   ├── export/
    │   │   │                       │   │   ├── PdfExportFragment.kt
    │   │   │                       │   │   ├── PdfExportShareContract.kt
    │   │   │                       │   │   └── PdfExportState.kt
    │   │   │                       │   └── net/
    │   │   │                       │       ├── PdfExportRepository.kt
    │   │   │                       │       ├── PdfExportRequestBody.kt
    │   │   │                       │       ├── PdfExportResponse.kt
    │   │   │                       │       └── PdfExportService.kt
    │   │   │                       ├── qr/
    │   │   │                       │   ├── VerifierInfoDialogFragment.kt
    │   │   │                       │   └── WalletQrScanFragment.kt
    │   │   │                       ├── ratconversion/
    │   │   │                       │   └── RatConversionFragment.kt
    │   │   │                       ├── renewal/
    │   │   │                       │   ├── QrCodeRenewalErrorCodes.kt
    │   │   │                       │   ├── QrCodeRenewalFragment.kt
    │   │   │                       │   ├── QrCodeRenewalViewModel.kt
    │   │   │                       │   ├── model/
    │   │   │                       │   │   ├── QrCodeRenewalResponse.kt
    │   │   │                       │   │   └── QrCodeRenewalViewState.kt
    │   │   │                       │   └── net/
    │   │   │                       │       ├── QrCodeRenewalBody.kt
    │   │   │                       │       ├── QrCodeRenewalRepository.kt
    │   │   │                       │       └── QrCodeRenewalService.kt
    │   │   │                       ├── transfercode/
    │   │   │                       │   ├── TransferCodeCreationFragment.kt
    │   │   │                       │   ├── TransferCodeCreationViewModel.kt
    │   │   │                       │   ├── TransferCodeDetailFragment.kt
    │   │   │                       │   ├── TransferCodeErrorCodes.kt
    │   │   │                       │   ├── TransferCodeHowToFragment.kt
    │   │   │                       │   ├── TransferCodeIntroFragment.kt
    │   │   │                       │   ├── TransferCodeViewModel.kt
    │   │   │                       │   ├── logic/
    │   │   │                       │   │   ├── Luhn.kt
    │   │   │                       │   │   └── TransferCodeCrypto.kt
    │   │   │                       │   ├── model/
    │   │   │                       │   │   ├── ConvertedCertificate.kt
    │   │   │                       │   │   ├── TransferCodeConversionState.kt
    │   │   │                       │   │   ├── TransferCodeCreationResponse.kt
    │   │   │                       │   │   ├── TransferCodeCreationState.kt
    │   │   │                       │   │   └── TransferCodeModel.kt
    │   │   │                       │   ├── net/
    │   │   │                       │   │   ├── CovidCert.kt
    │   │   │                       │   │   ├── CovidCertDelivery.kt
    │   │   │                       │   │   ├── DeliveryRegistration.kt
    │   │   │                       │   │   ├── DeliveryRepository.kt
    │   │   │                       │   │   ├── DeliveryService.kt
    │   │   │                       │   │   └── RequestDeliveryPayload.kt
    │   │   │                       │   ├── view/
    │   │   │                       │   │   ├── TransferCodeBubbleView.kt
    │   │   │                       │   │   ├── TransferCodeView.kt
    │   │   │                       │   │   └── TransferCodeWaitingView.kt
    │   │   │                       │   └── worker/
    │   │   │                       │       └── TransferWorker.kt
    │   │   │                       ├── travel/
    │   │   │                       │   ├── ForeignValidityFragment.kt
    │   │   │                       │   ├── ForeignValidityViewModel.kt
    │   │   │                       │   └── ForeignValidityViewState.kt
    │   │   │                       ├── util/
    │   │   │                       │   ├── BitmapUtil.kt
    │   │   │                       │   ├── ModeValidityStateUtil.kt
    │   │   │                       │   ├── NotificationUtil.kt
    │   │   │                       │   ├── QrCode.kt
    │   │   │                       │   └── VerificationStateUtil.kt
    │   │   │                       └── vaccination/
    │   │   │                           ├── appointment/
    │   │   │                           │   └── VaccinationAppointmentFragment.kt
    │   │   │                           └── hint/
    │   │   │                               └── VaccinationHintViewModel.kt
    │   │   ├── play/
    │   │   │   ├── listings/
    │   │   │   │   ├── de-DE/
    │   │   │   │   │   ├── full-description.txt
    │   │   │   │   │   ├── short-description.txt
    │   │   │   │   │   └── title.txt
    │   │   │   │   ├── en-US/
    │   │   │   │   │   ├── full-description.txt
    │   │   │   │   │   ├── short-description.txt
    │   │   │   │   │   └── title.txt
    │   │   │   │   ├── fr-FR/
    │   │   │   │   │   ├── full-description.txt
    │   │   │   │   │   ├── short-description.txt
    │   │   │   │   │   └── title.txt
    │   │   │   │   └── it-IT/
    │   │   │   │       ├── full-description.txt
    │   │   │   │       ├── short-description.txt
    │   │   │   │       └── title.txt
    │   │   │   └── release-notes/
    │   │   │       └── en-US/
    │   │   │           └── default.txt
    │   │   └── res/
    │   │       ├── color/
    │   │       │   └── text_color_button.xml
    │   │       ├── drawable/
    │   │       │   ├── bg_add_certificate_option.xml
    │   │       │   ├── bg_border.xml
    │   │       │   ├── bg_bordered_button.xml
    │   │       │   ├── bg_bubble_bottom_left.xml
    │   │       │   ├── bg_certificate_bottom.xml
    │   │       │   ├── bg_certificate_bubble.xml
    │   │       │   ├── bg_certificate_bubble_bundesrot.xml
    │   │       │   ├── bg_certificate_bubble_ripple.xml
    │   │       │   ├── bg_certificate_detail_note.xml
    │   │       │   ├── bg_certificate_top.xml
    │   │       │   ├── bg_info_banner.xml
    │   │       │   ├── bg_type_bubble_small.xml
    │   │       │   ├── circle_white.xml
    │   │       │   ├── cutout_left.xml
    │   │       │   ├── cutout_right.xml
    │   │       │   ├── ic_add_certificate.xml
    │   │       │   ├── ic_arrow_right.xml
    │   │       │   ├── ic_calendar.xml
    │   │       │   ├── ic_certificate_light.xml
    │   │       │   ├── ic_check_mark.xml
    │   │       │   ├── ic_cloud.xml
    │   │       │   ├── ic_corner_offline.xml
    │   │       │   ├── ic_corner_process_error.xml
    │   │       │   ├── ic_covid_check_app.xml
    │   │       │   ├── ic_data_protection.xml
    │   │       │   ├── ic_drag.xml
    │   │       │   ├── ic_exchange.xml
    │   │       │   ├── ic_expire_1.xml
    │   │       │   ├── ic_expire_2.xml
    │   │       │   ├── ic_expire_3.xml
    │   │       │   ├── ic_expire_4.xml
    │   │       │   ├── ic_expire_5.xml
    │   │       │   ├── ic_expire_6.xml
    │   │       │   ├── ic_expire_7.xml
    │   │       │   ├── ic_faq_image.xml
    │   │       │   ├── ic_flag_ch.xml
    │   │       │   ├── ic_header_slim.xml
    │   │       │   ├── ic_launcher_background.xml
    │   │       │   ├── ic_launcher_foreground.xml
    │   │       │   ├── ic_list.xml
    │   │       │   ├── ic_online.xml
    │   │       │   ├── ic_pdf.xml
    │   │       │   ├── ic_pen_write.xml
    │   │       │   ├── ic_qr_certificate.xml
    │   │       │   ├── ic_qrcode.xml
    │   │       │   ├── ic_qrcode_add.xml
    │   │       │   ├── ic_qrcode_icon_placeholder.xml
    │   │       │   ├── ic_qrcode_scan.xml
    │   │       │   ├── ic_scan_code.xml
    │   │       │   ├── ic_transfer_code_list_failed.xml
    │   │       │   ├── ic_transfer_code_list_valid.xml
    │   │       │   ├── ic_transfer_notification.xml
    │   │       │   ├── ic_validation.xml
    │   │       │   ├── icon_ag.xml
    │   │       │   ├── icon_ai.xml
    │   │       │   ├── icon_ar.xml
    │   │       │   ├── icon_be.xml
    │   │       │   ├── icon_bl.xml
    │   │       │   ├── icon_bs.xml
    │   │       │   ├── icon_fr.xml
    │   │       │   ├── icon_ge.xml
    │   │       │   ├── icon_gl.xml
    │   │       │   ├── icon_gr.xml
    │   │       │   ├── icon_ju.xml
    │   │       │   ├── icon_lu.xml
    │   │       │   ├── icon_ne.xml
    │   │       │   ├── icon_nw.xml
    │   │       │   ├── icon_ow.xml
    │   │       │   ├── icon_sg.xml
    │   │       │   ├── icon_sh.xml
    │   │       │   ├── icon_so.xml
    │   │       │   ├── icon_sz.xml
    │   │       │   ├── icon_tg.xml
    │   │       │   ├── icon_ti.xml
    │   │       │   ├── icon_ur.xml
    │   │       │   ├── icon_vd.xml
    │   │       │   ├── icon_vs.xml
    │   │       │   ├── icon_zg.xml
    │   │       │   ├── icon_zh.xml
    │   │       │   ├── illu_add_certificate.xml
    │   │       │   ├── illu_faq_transfer_code.xml
    │   │       │   ├── illu_home_empty_state.xml
    │   │       │   ├── illu_how_it_works.xml
    │   │       │   ├── illu_how_to_scan.xml
    │   │       │   ├── illu_onboarding_covid_certificate.xml
    │   │       │   ├── illu_onboarding_hero.xml
    │   │       │   ├── illu_onboarding_privacy.xml
    │   │       │   ├── illu_transfer_code_failed.xml
    │   │       │   ├── illu_transfer_code_intro.xml
    │   │       │   ├── illu_transfer_code_waiting_phone.xml
    │   │       │   ├── illu_transfer_code_waiting_ripple.xml
    │   │       │   ├── illu_transfer_code_waiting_shadow.xml
    │   │       │   ├── illu_updateboarding_certificate_light.xml
    │   │       │   └── oval_horizontal.xml
    │   │       ├── drawable-v24/
    │   │       │   └── ic_launcher_foreground.xml
    │   │       ├── layout/
    │   │       │   ├── activity_main.xml
    │   │       │   ├── dialog_fragment_certificate_banner_info.xml
    │   │       │   ├── dialog_fragment_mode_info.xml
    │   │       │   ├── dialog_fragment_refresh_button_info.xml
    │   │       │   ├── fragment_certificate_add.xml
    │   │       │   ├── fragment_certificate_detail.xml
    │   │       │   ├── fragment_certificate_light_conversion.xml
    │   │       │   ├── fragment_certificate_light_detail.xml
    │   │       │   ├── fragment_certificate_light_pager.xml
    │   │       │   ├── fragment_certificate_pager.xml
    │   │       │   ├── fragment_certificates_list.xml
    │   │       │   ├── fragment_foreign_validity.xml
    │   │       │   ├── fragment_home.xml
    │   │       │   ├── fragment_how_to_scan.xml
    │   │       │   ├── fragment_onboarding_agb.xml
    │   │       │   ├── fragment_onboarding_content.xml
    │   │       │   ├── fragment_onboarding_intro.xml
    │   │       │   ├── fragment_onboarding_pre_info.xml
    │   │       │   ├── fragment_pdf_export.xml
    │   │       │   ├── fragment_qr_code_renewal.xml
    │   │       │   ├── fragment_qr_scan.xml
    │   │       │   ├── fragment_rat_conversion.xml
    │   │       │   ├── fragment_transfer_code_creation.xml
    │   │       │   ├── fragment_transfer_code_detail.xml
    │   │       │   ├── fragment_transfer_code_howto.xml
    │   │       │   ├── fragment_transfer_code_intro.xml
    │   │       │   ├── fragment_transfer_code_pager.xml
    │   │       │   ├── fragment_updateboarding_agb.xml
    │   │       │   ├── fragment_updateboarding_certificate_light.xml
    │   │       │   ├── fragment_updateboarding_validity_1.xml
    │   │       │   ├── fragment_updateboarding_validity_2.xml
    │   │       │   ├── fragment_updateboarding_validity_3.xml
    │   │       │   ├── fragment_updateboarding_validity_4.xml
    │   │       │   ├── fragment_vaccination_appointment.xml
    │   │       │   ├── item_certificate_list.xml
    │   │       │   ├── item_debug_certificate_list.xml
    │   │       │   ├── item_detail_divider.xml
    │   │       │   ├── item_detail_mode.xml
    │   │       │   ├── item_detail_mode_refresh.xml
    │   │       │   ├── item_detail_modes_list.xml
    │   │       │   ├── item_detail_title.xml
    │   │       │   ├── item_detail_value.xml
    │   │       │   ├── item_detail_value_without_label.xml
    │   │       │   ├── item_foreign_rules_check_hint.xml
    │   │       │   ├── item_header_not_empty.xml
    │   │       │   ├── item_icon_text_info.xml
    │   │       │   ├── item_mode_list_info.xml
    │   │       │   ├── item_transfer_code_list.xml
    │   │       │   ├── item_vaccination_appointment_canton.xml
    │   │       │   ├── partial_certificate_detail_banners.xml
    │   │       │   ├── partial_home_add_certificate_options.xml
    │   │       │   ├── view_transfer_code.xml
    │   │       │   ├── view_transfer_code_bubble.xml
    │   │       │   └── view_transfer_code_waiting.xml
    │   │       ├── mipmap-anydpi-v26/
    │   │       │   ├── ic_launcher.xml
    │   │       │   └── ic_launcher_round.xml
    │   │       └── xml/
    │   │           └── filepaths.xml
    │   ├── prod/
    │   │   └── java/
    │   │       └── ch/
    │   │           └── admin/
    │   │               └── bag/
    │   │                   └── covidcertificate/
    │   │                       └── wallet/
    │   │                           └── debug/
    │   │                               └── WalletDebugFragment.kt
    │   └── test/
    │       └── java/
    │           └── ch/
    │               └── admin/
    │                   └── bag/
    │                       └── covidcertificate/
    │                           └── wallet/
    │                               └── transfercode/
    │                                   ├── LuhnTest.kt
    │                                   └── LuhnTestWrongCodes.kt
    └── testKeystore
Download .txt
SYMBOL INDEX (14 symbols across 4 files)

FILE: apkdiff.py
  function compareFiles (line 7) | def compareFiles(first, second):
  function compare (line 19) | def compare(first, second):

FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/util/SingleLiveEvent.java
  class SingleLiveEvent (line 38) | public class SingleLiveEvent<T> extends MutableLiveData<T> {
    method observe (line 44) | @MainThread
    method setValue (line 62) | @MainThread
    method call (line 71) | @MainThread

FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/util/UlTagHandler.java
  class UlTagHandler (line 20) | public class UlTagHandler implements Html.TagHandler {
    method handleTag (line 25) | @Override
    method start (line 43) | private static void start(Editable text, Object mark) {
    method end (line 48) | private static void end(Editable text, Class<?> kind, Object... replac...
    method getLast (line 60) | private static Object getLast(Spanned text, Class<?> kind) {
    class Ul (line 68) | private static class Ul { }

FILE: common/src/main/java/ch/admin/bag/covidcertificate/common/util/UrlUtil.java
  class UrlUtil (line 19) | public class UrlUtil {
    method openUrl (line 21) | public static void openUrl(Context context, String url) {
Condensed preview — 643 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,302K chars).
[
  {
    "path": ".github/actions/gradle_docker/action.yml",
    "chars": 306,
    "preview": "name: 'GradleDocker'\ndescription: 'Run gradle inside Docker image'\ninputs:\n  gradle-cmd:  # id of input\n    description:"
  },
  {
    "path": ".github/actions/gradle_docker/main.sh",
    "chars": 41,
    "preview": "#!/bin/sh\n\ncd $GITHUB_WORKSPACE\ngradle $1"
  },
  {
    "path": ".github/workflows/appcenter_verifier_abn.yml",
    "chars": 889,
    "preview": "name: Build Verifier ABN\n\non:\n  push:\n    branches:\n      - main\n      - 'release/**'\n  pull_request:\n    branches:\n    "
  },
  {
    "path": ".github/workflows/appcenter_verifier_dev.yml",
    "chars": 917,
    "preview": "name: Build Verifier DEV\n\non:\n  push:\n    branches:\n      - main\n      - 'release/**'\n  pull_request:\n    branches:\n    "
  },
  {
    "path": ".github/workflows/appcenter_verifier_prod.yml",
    "chars": 1112,
    "preview": "name: Build Verifier PROD\n\non:\n  push:\n    branches:\n      - main\n      - 'release/**'\n  pull_request:\n    branches:\n   "
  },
  {
    "path": ".github/workflows/appcenter_verifier_prodfdroid.yml",
    "chars": 1137,
    "preview": "name: Build Verifier PRODFDROID\n\non:\n  push:\n    branches:\n      - main\n      - 'release/**'\n  pull_request:\n    branche"
  },
  {
    "path": ".github/workflows/appcenter_wallet_abn.yml",
    "chars": 879,
    "preview": "name: Build Wallet ABN\n\non:\n  push:\n    branches:\n      - main\n      - 'release/**'\n  pull_request:\n    branches:\n      "
  },
  {
    "path": ".github/workflows/appcenter_wallet_dev.yml",
    "chars": 907,
    "preview": "name: Build Wallet DEV\n\non:\n  push:\n    branches:\n      - main\n      - 'release/**'\n  pull_request:\n    branches:\n      "
  },
  {
    "path": ".github/workflows/appcenter_wallet_prod.yml",
    "chars": 1096,
    "preview": "name: Build Wallet PROD\n\non:\n  push:\n    branches:\n      - main\n      - 'release/**'\n  pull_request:\n    branches:\n     "
  },
  {
    "path": ".github/workflows/appcenter_wallet_prodfdroid.yml",
    "chars": 1121,
    "preview": "name: Build Wallet PRODFDROID\n\non:\n  push:\n    branches:\n      - main\n      - 'release/**'\n  pull_request:\n    branches:"
  },
  {
    "path": ".github/workflows/browserstack_wallet_abn.yml",
    "chars": 4730,
    "preview": "name: Build Browserstack UI-Test Wallet\n\non:\n  push:\n    branches:\n      - main\n      - 'release/**'\n  pull_request:\n   "
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 1089,
    "preview": "name: Build\n\non:\n  push:\n    branches:\n      - main\n      - 'release/**'\n  pull_request:\njobs:\n  build:\n    name: Build\n"
  },
  {
    "path": ".github/workflows/gradle-wrapper-validation.yml",
    "chars": 299,
    "preview": "name: Validate Gradle Wrapper\n\non: [push, pull_request]\n\njobs:\n  validation:\n    name: Validation\n    runs-on: ubuntu-la"
  },
  {
    "path": ".gitignore",
    "chars": 1471,
    "preview": "# Built application files\n*.apk\n*.aar\n*.ap_\n*.aab\n\n# Files for the ART/Dalvik VM\n*.dex\n\n# Java class files\n*.class\n\n# Ge"
  },
  {
    "path": "Dockerfile",
    "chars": 900,
    "preview": "FROM gradle:7.2-jdk11\n\nENV ANDROID_SDK_URL https://dl.google.com/android/repository/commandlinetools-linux-7583922_lates"
  },
  {
    "path": "LICENSE",
    "chars": 16725,
    "preview": "Mozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\""
  },
  {
    "path": "README.md",
    "chars": 4686,
    "preview": "# COVID Certificate Apps - Android\n\n[![License: MPL 2.0](https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg)"
  },
  {
    "path": "REPRODUCIBLE_BUILDS.md",
    "chars": 1992,
    "preview": "# Reproducible Builds\n\nThis document outlines how you can reproduce the Android app.\n\nThe instructions below are for the"
  },
  {
    "path": "apkdiff.py",
    "chars": 1916,
    "preview": "\n# Taken from https://github.com/DrKLO/Telegram/blob/master/apkdiff.py on June 4th, 2020\n\nimport sys\nfrom zipfile import"
  },
  {
    "path": "build.gradle",
    "chars": 998,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "buildAndCompare.sh",
    "chars": 3481,
    "preview": "#!/bin/bash\n\n# Script to automate the building and comparing of the CovidCertificate apps\n#\n# The first and only argumen"
  },
  {
    "path": "common/.gitignore",
    "chars": 6,
    "preview": "/build"
  },
  {
    "path": "common/build.gradle",
    "chars": 2649,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/consumer-rules.pro",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "common/proguard-rules.pro",
    "chars": 750,
    "preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
  },
  {
    "path": "common/src/abn/java/ch/admin/bag/covidcertificate/common/debug/DebugFragment.kt",
    "chars": 626,
    "preview": "package ch.admin.bag.covidcertificate.common.debug\n/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>"
  },
  {
    "path": "common/src/dev/java/ch/admin/bag/covidcertificate/common/debug/DebugFragment.kt",
    "chars": 2025,
    "preview": "package ch.admin.bag.covidcertificate.common.debug\n/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>"
  },
  {
    "path": "common/src/dev/java/ch/admin/bag/covidcertificate/common/debug/DebugSecureStorage.kt",
    "chars": 1222,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/dev/res/xml/network_security_config.xml",
    "chars": 635,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ Copyright (c) 2020 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ T"
  },
  {
    "path": "common/src/main/AndroidManifest.xml",
    "chars": 500,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/assets/impressum/de/impressum.html",
    "chars": 2895,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/assets/impressum/de/licence.html",
    "chars": 2684,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/assets/impressum/en/impressum.html",
    "chars": 2928,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/assets/impressum/en/licence.html",
    "chars": 2684,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/assets/impressum/fr/impressum.html",
    "chars": 2978,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/assets/impressum/fr/licence.html",
    "chars": 2684,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/assets/impressum/it/impressum.html",
    "chars": 2962,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/assets/impressum/it/licence.html",
    "chars": 2683,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/assets/impressum/rm/impressum.html",
    "chars": 2897,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/assets/impressum/rm/licence.html",
    "chars": 2684,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/BaseActivity.kt",
    "chars": 509,
    "preview": "package ch.admin.bag.covidcertificate.common\n\nimport android.content.Context\nimport androidx.appcompat.app.AppCompatActi"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/browserstack/AirplaneMode.kt",
    "chars": 409,
    "preview": "/*\n * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/browserstack/BadNetwork.kt",
    "chars": 407,
    "preview": "/*\n * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/browserstack/Normal.kt",
    "chars": 403,
    "preview": "/*\n * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/browserstack/Onboarding.kt",
    "chars": 407,
    "preview": "/*\n * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/config/CertificateRenewalInfoDetailModel.kt",
    "chars": 536,
    "preview": "/*\n * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/config/CertificateRenewalInfoModel.kt",
    "chars": 612,
    "preview": "/*\n * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/config/CertificateRenewalType.kt",
    "chars": 507,
    "preview": "/*\n * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/config/CheckModesInfosModel.kt",
    "chars": 1296,
    "preview": "package ch.admin.bag.covidcertificate.common.config\n\nimport com.squareup.moshi.JsonClass\n\n//for verifier\n@JsonClass(gene"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/config/ConfigModel.kt",
    "chars": 5237,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/config/ConfigViewModel.kt",
    "chars": 1430,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/config/CovidCertificateNewsItem.kt",
    "chars": 574,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/config/EolBannerInfoModel.kt",
    "chars": 535,
    "preview": "package ch.admin.bag.covidcertificate.common.config\n\nimport com.squareup.moshi.JsonClass\nimport java.io.Serializable\n\n@J"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/config/FaqEntryModel.kt",
    "chars": 585,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/config/FaqIntroSection.kt",
    "chars": 519,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/config/FaqModel.kt",
    "chars": 632,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/config/ForeignRulesHintModel.kt",
    "chars": 525,
    "preview": "/*\n * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/config/InfoBoxModel.kt",
    "chars": 1569,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/config/InfoCovidCertificateNews.kt",
    "chars": 595,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/config/RefreshButtonInfoModel.kt",
    "chars": 672,
    "preview": "/*\n * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/config/VaccinationBookingInfoModel.kt",
    "chars": 662,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/config/VaccinationHintModel.kt",
    "chars": 519,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/data/ConfigSecureStorage.kt",
    "chars": 3065,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/dialog/InfoDialogFragment.kt",
    "chars": 2665,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/exception/HttpIOException.kt",
    "chars": 852,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/exception/TimeDeviationException.kt",
    "chars": 110,
    "preview": "package ch.admin.bag.covidcertificate.common.exception\n\nclass TimeDeviationException : IllegalStateException()"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/extensions/ContextExtensions.kt",
    "chars": 845,
    "preview": "/*\n * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/extensions/DccCertExtensions.kt",
    "chars": 663,
    "preview": "package ch.admin.bag.covidcertificate.common.extensions\n\nimport ch.admin.bag.covidcertificate.sdk.core.extensions.firstP"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/extensions/LifecycleOwnerExtensions.kt",
    "chars": 917,
    "preview": "/*\n * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/extensions/OkHttpExtensions.kt",
    "chars": 342,
    "preview": "package ch.admin.bag.covidcertificate.common.extensions\n\nimport okhttp3.OkHttpClient\nimport java.util.concurrent.TimeUni"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/extensions/WindowExtensions.kt",
    "chars": 472,
    "preview": "package ch.admin.bag.covidcertificate.common.extensions\n\nimport android.view.Window\nimport android.view.WindowManager\n\nf"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/faq/FaqAdapter.kt",
    "chars": 2086,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/faq/FaqFragment.kt",
    "chars": 2227,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/faq/FaqItem.kt",
    "chars": 3496,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/faq/FaqViewHolder.kt",
    "chars": 639,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/faq/model/Header.kt",
    "chars": 791,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/html/BuildInfo.kt",
    "chars": 579,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/html/ImprintFragment.kt",
    "chars": 5031,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/net/ConfigRepository.kt",
    "chars": 4626,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/net/ConfigService.kt",
    "chars": 805,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/onboarding/BaseOnboardingActivity.kt",
    "chars": 1712,
    "preview": "/*\n * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/onboarding/SimpleOnboardingPagerAdapter.kt",
    "chars": 897,
    "preview": "/*\n * Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/qr/CameraPermissionExplanationDialog.kt",
    "chars": 1575,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/qr/KittlerBinarizer.kt",
    "chars": 2118,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/qr/QRCodeReaderHelper.kt",
    "chars": 4061,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/qr/QrScanFragment.kt",
    "chars": 11322,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/qr/QrScannerState.kt",
    "chars": 439,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/settings/SettingsFragment.kt",
    "chars": 2027,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/util/AssetUtil.kt",
    "chars": 5538,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/util/CutOutEdgeTreatment.kt",
    "chars": 2471,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/util/EnvironmentUtil.kt",
    "chars": 765,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/util/ErrorCodeUtil.kt",
    "chars": 1145,
    "preview": "package ch.admin.bag.covidcertificate.common.util\n\nimport ch.admin.bag.covidcertificate.sdk.core.models.state.CheckNatio"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/util/ErrorHelper.kt",
    "chars": 2398,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/util/ErrorState.kt",
    "chars": 1192,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/util/HorizontalMarginItemDecoration.kt",
    "chars": 830,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/util/LocaleUtil.kt",
    "chars": 633,
    "preview": "package ch.admin.bag.covidcertificate.common.util\n\nimport android.content.Context\nimport android.content.res.Configurati"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/util/SingleLiveEvent.java",
    "chars": 2260,
    "preview": "/*\n *  Copyright 2017 Google Inc.\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/util/StringUtil.kt",
    "chars": 2738,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/util/UiUtil.kt",
    "chars": 691,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/util/UlTagHandler.java",
    "chars": 1864,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/util/UrlUtil.java",
    "chars": 878,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/views/MarginItemDecoration.kt",
    "chars": 631,
    "preview": "package ch.admin.bag.covidcertificate.common.views\n\nimport android.content.Context\nimport android.graphics.Rect\nimport a"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/views/ViewExtensions.kt",
    "chars": 4246,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/java/ch/admin/bag/covidcertificate/common/views/WindowInsetsLayout.kt",
    "chars": 2951,
    "preview": "/*\n * Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n *\n * This Source Code Form is subject to the term"
  },
  {
    "path": "common/src/main/res/anim/fragment_open_enter.xml",
    "chars": 1136,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/anim/fragment_open_exit.xml",
    "chars": 1130,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/anim/slide_enter.xml",
    "chars": 807,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/anim/slide_exit.xml",
    "chars": 626,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/anim/slide_pop_enter.xml",
    "chars": 625,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/anim/slide_pop_exit.xml",
    "chars": 809,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/color/selector_black_or_white.xml",
    "chars": 559,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/color/selector_blue_or_white.xml",
    "chars": 558,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/color/selector_grey_or_blue.xml",
    "chars": 556,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/color/selector_grey_or_white.xml",
    "chars": 557,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/color/selector_transparent_or_blue.xml",
    "chars": 571,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/color/selector_white_or_black.xml",
    "chars": 559,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/color/selector_white_or_blue.xml",
    "chars": 558,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/color/text_radio_checkable.xml",
    "chars": 623,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/drawable/bg_button_default.xml",
    "chars": 863,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/drawable/bg_button_red.xml",
    "chars": 866,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/drawable/bg_button_white.xml",
    "chars": 880,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/drawable/bg_corners_top_left.xml",
    "chars": 632,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/drawable/bg_dialog.xml",
    "chars": 668,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/drawable/bg_pill.xml",
    "chars": 548,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ T"
  },
  {
    "path": "common/src/main/res/drawable/bg_rect_rounded_sheet.xml",
    "chars": 566,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/drawable/bg_rect_rounded_small.xml",
    "chars": 568,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/drawable/bg_rect_rounded_small_blue_ripple.xml",
    "chars": 861,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/drawable/bg_rect_rounded_small_checkable.xml",
    "chars": 1074,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/drawable/bg_rect_rounded_small_red.xml",
    "chars": 570,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/drawable/btn_radio_checkable.xml",
    "chars": 720,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/drawable/dot_black.xml",
    "chars": 643,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/drawable/dot_grey.xml",
    "chars": 642,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/drawable/dot_white.xml",
    "chars": 643,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/drawable/header_bottom.xml",
    "chars": 705,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/drawable/header_collapsed_shadow.xml",
    "chars": 611,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ "
  },
  {
    "path": "common/src/main/res/drawable/ic_1g.xml",
    "chars": 1381,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"33dp\"\n    android:height=\"32dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_2g.xml",
    "chars": 1989,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"33dp\"\n    android:height=\"32dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_2g_green.xml",
    "chars": 1937,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_2g_grey.xml",
    "chars": 1961,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"33dp\"\n    android:height=\"32dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_2g_plus.xml",
    "chars": 2361,
    "preview": "<!--\n  ~ Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_3g.xml",
    "chars": 2565,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"33dp\"\n    android:height=\"32dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_arrow_contract.xml",
    "chars": 723,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_arrow_expand.xml",
    "chars": 722,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_arrow_forward.xml",
    "chars": 521,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_bund_small.xml",
    "chars": 1083,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_bundwappen_big.xml",
    "chars": 1085,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_call.xml",
    "chars": 644,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_cam_off.xml",
    "chars": 927,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_camera_switch.xml",
    "chars": 971,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_check_filled.xml",
    "chars": 724,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_check_green.xml",
    "chars": 900,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_check_grey.xml",
    "chars": 899,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_check_large.xml",
    "chars": 1071,
    "preview": "<!--\r\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\r\n  ~\r\n  ~ This Source Code Form is subject to "
  },
  {
    "path": "common/src/main/res/drawable/ic_checkbox_empty.xml",
    "chars": 460,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_checkbox_filled.xml",
    "chars": 569,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_close.xml",
    "chars": 689,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_close_red.xml",
    "chars": 1058,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_dot.xml",
    "chars": 666,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_double_check.xml",
    "chars": 861,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"25dp\"\n    android:height=\"24dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_error.xml",
    "chars": 981,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_error_blue.xml",
    "chars": 565,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_error_grey.xml",
    "chars": 952,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_error_large.xml",
    "chars": 1000,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_error_orange.xml",
    "chars": 954,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_error_triangle.xml",
    "chars": 1166,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_expire_i.xml",
    "chars": 762,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"25dp\"\n    android:height=\"24dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_faq.xml",
    "chars": 1328,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_header_slim.xml",
    "chars": 757,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_how_it_works_image.xml",
    "chars": 3992,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_info.xml",
    "chars": 1034,
    "preview": "<!--\n  ~ Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_info_alert.xml",
    "chars": 620,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"25dp\"\n    android:height=\"24dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_info_blue.xml",
    "chars": 980,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_info_outline.xml",
    "chars": 1049,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_invalid_grey.xml",
    "chars": 904,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_invalid_red.xml",
    "chars": 903,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_light_off.xml",
    "chars": 1387,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_light_off_blue.xml",
    "chars": 1361,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_light_on.xml",
    "chars": 2081,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_light_on_black.xml",
    "chars": 2081,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_link_external.xml",
    "chars": 1338,
    "preview": "<!--\r\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\r\n  ~\r\n  ~ This Source Code Form is subject to "
  },
  {
    "path": "common/src/main/res/drawable/ic_load.xml",
    "chars": 1163,
    "preview": "<!--\r\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\r\n  ~\r\n  ~ This Source Code Form is subject to "
  },
  {
    "path": "common/src/main/res/drawable/ic_no1g.xml",
    "chars": 1326,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"33dp\"\n    android:height=\"32dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_no2g.xml",
    "chars": 1747,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"33dp\"\n    android:height=\"32dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_no3g.xml",
    "chars": 2312,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"33dp\"\n    android:height=\"32dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_no_2_g_plus_height.xml",
    "chars": 3097,
    "preview": "<!--\n  ~ Copyright (c) 2022 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_no_connection.xml",
    "chars": 1777,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_no_connection_large.xml",
    "chars": 1782,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_notification.xml",
    "chars": 1050,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_notification_filled.xml",
    "chars": 820,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_offline.xml",
    "chars": 1218,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_offline_large.xml",
    "chars": 1190,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_offline_orange.xml",
    "chars": 1218,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_one.xml",
    "chars": 975,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_phone.xml",
    "chars": 742,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"25dp\"\n    android:height=\"24dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_plus.xml",
    "chars": 466,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_plus_green.xml",
    "chars": 467,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n  "
  },
  {
    "path": "common/src/main/res/drawable/ic_privacy.xml",
    "chars": 1716,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_privacy_grey.xml",
    "chars": 1720,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_process_error.xml",
    "chars": 1423,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  },
  {
    "path": "common/src/main/res/drawable/ic_process_error_grey.xml",
    "chars": 1394,
    "preview": "<!--\n  ~ Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>\n  ~\n  ~ This Source Code Form is subject to the"
  }
]

// ... and 443 more files (download for full content)

About this extraction

This page contains the full source code of the admin-ch/CovidCertificate-App-Android GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 643 files (2.9 MB), approximately 799.7k tokens, and a symbol index with 14 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!