[
  {
    "path": ".gitignore",
    "content": "\n# Created by https://www.toptal.com/developers/gitignore/api/rider,visualstudio,visualstudiocode\n# Edit at https://www.toptal.com/developers/gitignore?templates=rider,visualstudio,visualstudiocode\n\n### Rider ###\n# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider\n# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839\n\n# User-specific stuff\n.idea/**/workspace.xml\n.idea/**/tasks.xml\n.idea/**/usage.statistics.xml\n.idea/**/dictionaries\n.idea/**/shelf\n\n# AWS User-specific\n.idea/**/aws.xml\n\n# Generated files\n.idea/**/contentModel.xml\n\n# Sensitive or high-churn files\n.idea/**/dataSources/\n.idea/**/dataSources.ids\n.idea/**/dataSources.local.xml\n.idea/**/sqlDataSources.xml\n.idea/**/dynamic.xml\n.idea/**/uiDesigner.xml\n.idea/**/dbnavigator.xml\n\n# Gradle\n.idea/**/gradle.xml\n.idea/**/libraries\n\n# Gradle and Maven with auto-import\n# When using Gradle or Maven with auto-import, you should exclude module files,\n# since they will be recreated, and may cause churn.  Uncomment if using\n# auto-import.\n# .idea/artifacts\n# .idea/compiler.xml\n# .idea/jarRepositories.xml\n# .idea/modules.xml\n# .idea/*.iml\n# .idea/modules\n# *.iml\n# *.ipr\n\n# CMake\ncmake-build-*/\n\n# Mongo Explorer plugin\n.idea/**/mongoSettings.xml\n\n# File-based project format\n*.iws\n\n# IntelliJ\nout/\n\n# mpeltonen/sbt-idea plugin\n.idea_modules/\n\n# JIRA plugin\natlassian-ide-plugin.xml\n\n# Cursive Clojure plugin\n.idea/replstate.xml\n\n# SonarLint plugin\n.idea/sonarlint/\n\n# Crashlytics plugin (for Android Studio and IntelliJ)\ncom_crashlytics_export_strings.xml\ncrashlytics.properties\ncrashlytics-build.properties\nfabric.properties\n\n# Editor-based Rest Client\n.idea/httpRequests\n\n# Android studio 3.1+ serialized cache file\n.idea/caches/build_file_checksums.ser\n\n### VisualStudioCode ###\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n!.vscode/*.code-snippets\n\n# Local History for Visual Studio Code\n.history/\n\n# Built Visual Studio Code Extensions\n*.vsix\n\n### VisualStudioCode Patch ###\n# Ignore all local history of files\n.history\n.ionide\n\n# Support for Project snippet scope\n\n### VisualStudio ###\n## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore\n\n# User-specific files\n*.rsuser\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Mono auto generated files\nmono_crash.*\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\n[Ww][Ii][Nn]32/\n[Aa][Rr][Mm]/\n[Aa][Rr][Mm]64/\nbld/\n[Bb]in/\n[Oo]bj/\n[Ll]og/\n[Ll]ogs/\n\n# Visual Studio 2015/2017 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# Visual Studio 2017 auto generated files\nGenerated\\ Files/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUnit\n*.VisualState.xml\nTestResult.xml\nnunit-*.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# Benchmark Results\nBenchmarkDotNet.Artifacts/\n\n# .NET Core\nproject.lock.json\nproject.fragment.lock.json\nartifacts/\n\n# ASP.NET Scaffolding\nScaffoldingReadMe.txt\n\n# StyleCop\nStyleCopReport.xml\n\n# Files built by Visual Studio\n*_i.c\n*_p.c\n*_h.h\n*.ilk\n*.meta\n*.obj\n*.iobj\n*.pch\n*.pdb\n*.ipdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*_wpftmp.csproj\n*.log\n*.tlog\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n*.VC.db\n*.VC.VC.opendb\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# Visual Studio Trace Files\n*.e2e\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# AxoCover is a Code Coverage Tool\n.axoCover/*\n!.axoCover/settings.json\n\n# Coverlet is a free, cross platform Code Coverage Tool\ncoverage*.json\ncoverage*.xml\ncoverage*.info\n\n# Visual Studio code coverage results\n*.coverage\n*.coveragexml\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# Note: Comment the next line if you want to checkin your web deploy settings,\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# Microsoft Azure Web App publish settings. Comment the next line if you want to\n# checkin your Azure Web App publish settings, but sensitive information contained\n# in these scripts will be unencrypted\nPublishScripts/\n\n# NuGet Packages\n*.nupkg\n# NuGet Symbol Packages\n*.snupkg\n# The packages folder can be ignored because of Package Restore\n**/[Pp]ackages/*\n# except build/, which is used as an MSBuild target.\n!**/[Pp]ackages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/[Pp]ackages/repositories.config\n# NuGet v3's project.json files produces more ignorable files\n*.nuget.props\n*.nuget.targets\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Windows Store app package directories and files\nAppPackages/\nBundleArtifacts/\nPackage.StoreAssociation.xml\n_pkginfo.txt\n*.appx\n*.appxbundle\n*.appxupload\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!?*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.jfm\n*.pfx\n*.publishsettings\norleans.codegen.cs\n\n# Including strong name files can present a security risk\n# (https://github.com/github/gitignore/pull/2483#issue-259490424)\n#*.snk\n\n# Since there are multiple workflows, uncomment next line to ignore bower_components\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\n#bower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\nServiceFabricBackup/\n*.rptproj.bak\n\n# SQL Server files\n*.mdf\n*.ldf\n*.ndf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n*.rptproj.rsuser\n*- [Bb]ackup.rdl\n*- [Bb]ackup ([0-9]).rdl\n*- [Bb]ackup ([0-9][0-9]).rdl\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\nnode_modules/\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)\n*.vbw\n\n# Visual Studio 6 auto-generated project file (contains which files were open etc.)\n*.vbp\n\n# Visual Studio 6 workspace and project file (working project files containing files to include in project)\n*.dsw\n*.dsp\n\n# Visual Studio 6 technical files\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\npaket-files/\n\n# FAKE - F# Make\n.fake/\n\n# CodeRush personal settings\n.cr/personal\n\n# Python Tools for Visual Studio (PTVS)\n__pycache__/\n*.pyc\n\n# Cake - Uncomment if you are using it\n# tools/**\n# !tools/packages.config\n\n# Tabs Studio\n*.tss\n\n# Telerik's JustMock configuration file\n*.jmconfig\n\n# BizTalk build output\n*.btp.cs\n*.btm.cs\n*.odx.cs\n*.xsd.cs\n\n# OpenCover UI analysis results\nOpenCover/\n\n# Azure Stream Analytics local run output\nASALocalRun/\n\n# MSBuild Binary and Structured Log\n*.binlog\n\n# NVidia Nsight GPU debugger configuration file\n*.nvuser\n\n# MFractors (Xamarin productivity tool) working folder\n.mfractor/\n\n# Local History for Visual Studio\n.localhistory/\n\n# Visual Studio History (VSHistory) files\n.vshistory/\n\n# BeatPulse healthcheck temp database\nhealthchecksdb\n\n# Backup folder for Package Reference Convert tool in Visual Studio 2017\nMigrationBackup/\n\n# Ionide (cross platform F# VS Code tools) working folder\n.ionide/\n\n# Fody - auto-generated XML schema\nFodyWeavers.xsd\n\n# VS Code files for those working on multiple tools\n*.code-workspace\n\n# Local History for Visual Studio Code\n\n# Windows Installer files from build outputs\n*.cab\n*.msi\n*.msix\n*.msm\n*.msp\n\n# JetBrains Rider\n*.sln.iml\n\n### VisualStudio Patch ###\n# Additional files built by Visual Studio\n\n# End of https://www.toptal.com/developers/gitignore/api/rider,visualstudio,visualstudiocode"
  },
  {
    "path": ".idea/.idea.MiScaleExporter/.idea/.name",
    "content": "MiScaleExporter"
  },
  {
    "path": ".idea/.idea.MiScaleExporter/.idea/encodings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"Encoding\" addBOMForNewFiles=\"with BOM under Windows, with no BOM otherwise\" />\n</project>"
  },
  {
    "path": ".idea/.idea.MiScaleExporter/.idea/indexLayout.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"UserContentModel\">\n    <attachedFolders />\n    <explicitIncludes />\n    <explicitExcludes />\n  </component>\n</project>"
  },
  {
    "path": ".idea/.idea.MiScaleExporter/.idea/misc.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"DesignSurface\">\n    <option name=\"filePathToZoomLevelMap\">\n      <map>\n        <entry key=\"..\\:/Projects/mi-scale-exporter/src/MiScaleExporter.Android/Resources/mipmap-anydpi-v26/icon.xml\" value=\"0.5520833333333334\" />\n        <entry key=\"..\\:/Projects/mi-scale-exporter/src/MiScaleExporter.Android/Resources/mipmap-anydpi-v26/icon_round.xml\" value=\"0.5520833333333334\" />\n      </map>\n    </option>\n  </component>\n  <component name=\"com.jetbrains.rider.android.RiderAndroidMiscFileCreationComponent\">\n    <option name=\"ENSURE_MISC_FILE_EXISTS\" value=\"true\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/.idea.MiScaleExporter/.idea/projectSettingsUpdater.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"RiderProjectSettingsUpdater\">\n    <option name=\"vcsConfiguration\" value=\"2\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/.idea.MiScaleExporter/.idea/vcs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"VcsDirectoryMappings\">\n    <mapping directory=\"$PROJECT_DIR$\" vcs=\"Git\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/.idea.miscale2garmin/.idea/.gitignore",
    "content": "﻿# Default ignored files\n/shelf/\n/workspace.xml\n# Rider ignored files\n/contentModel.xml\n/.idea.miscale2garmin.iml\n/.idea.MiScaleExporter.iml\n/projectSettingsUpdater.xml\n/modules.xml\n# Editor-based HTTP Client requests\n/httpRequests/\n# Datasource local storage ignored files\n/dataSources/\n/dataSources.local.xml\n"
  },
  {
    "path": ".idea/.idea.miscale2garmin/.idea/.name",
    "content": "miscale2garmin"
  },
  {
    "path": ".idea/.idea.miscale2garmin/.idea/encodings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"Encoding\" addBOMForNewFiles=\"with BOM under Windows, with no BOM otherwise\" />\n</project>"
  },
  {
    "path": ".idea/.idea.miscale2garmin/.idea/indexLayout.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"UserContentModel\">\n    <attachedFolders />\n    <explicitIncludes />\n    <explicitExcludes />\n  </component>\n</project>"
  },
  {
    "path": ".idea/.idea.miscale2garmin/.idea/misc.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"com.jetbrains.rider.android.RiderAndroidMiscFileCreationComponent\">\n    <option name=\"ENSURE_MISC_FILE_EXISTS\" value=\"true\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/.idea.miscale2garmin/.idea/vcs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"VcsDirectoryMappings\">\n    <mapping directory=\"$PROJECT_DIR$\" vcs=\"Git\" />\n  </component>\n</project>"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "MiScaleExporter.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.0.32112.339\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"MiScaleExporter.MAUI\", \"src\\MiScaleExporter.MAUI\\MiScaleExporter.MAUI.csproj\", \"{39C1BB45-DB3C-4C1A-A3C0-5CBB35C753D0}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tDebug|iPhone = Debug|iPhone\n\t\tDebug|iPhoneSimulator = Debug|iPhoneSimulator\n\t\tRelease|Any CPU = Release|Any CPU\n\t\tRelease|iPhone = Release|iPhone\n\t\tRelease|iPhoneSimulator = Release|iPhoneSimulator\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{39C1BB45-DB3C-4C1A-A3C0-5CBB35C753D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{39C1BB45-DB3C-4C1A-A3C0-5CBB35C753D0}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{39C1BB45-DB3C-4C1A-A3C0-5CBB35C753D0}.Debug|Any CPU.Deploy.0 = Debug|Any CPU\n\t\t{39C1BB45-DB3C-4C1A-A3C0-5CBB35C753D0}.Debug|iPhone.ActiveCfg = Debug|Any CPU\n\t\t{39C1BB45-DB3C-4C1A-A3C0-5CBB35C753D0}.Debug|iPhone.Build.0 = Debug|Any CPU\n\t\t{39C1BB45-DB3C-4C1A-A3C0-5CBB35C753D0}.Debug|iPhone.Deploy.0 = Debug|Any CPU\n\t\t{39C1BB45-DB3C-4C1A-A3C0-5CBB35C753D0}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU\n\t\t{39C1BB45-DB3C-4C1A-A3C0-5CBB35C753D0}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU\n\t\t{39C1BB45-DB3C-4C1A-A3C0-5CBB35C753D0}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU\n\t\t{39C1BB45-DB3C-4C1A-A3C0-5CBB35C753D0}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{39C1BB45-DB3C-4C1A-A3C0-5CBB35C753D0}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{39C1BB45-DB3C-4C1A-A3C0-5CBB35C753D0}.Release|Any CPU.Deploy.0 = Release|Any CPU\n\t\t{39C1BB45-DB3C-4C1A-A3C0-5CBB35C753D0}.Release|iPhone.ActiveCfg = Release|Any CPU\n\t\t{39C1BB45-DB3C-4C1A-A3C0-5CBB35C753D0}.Release|iPhone.Build.0 = Release|Any CPU\n\t\t{39C1BB45-DB3C-4C1A-A3C0-5CBB35C753D0}.Release|iPhone.Deploy.0 = Release|Any CPU\n\t\t{39C1BB45-DB3C-4C1A-A3C0-5CBB35C753D0}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU\n\t\t{39C1BB45-DB3C-4C1A-A3C0-5CBB35C753D0}.Release|iPhoneSimulator.Build.0 = Release|Any CPU\n\t\t{39C1BB45-DB3C-4C1A-A3C0-5CBB35C753D0}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {44FCA853-2BA4-4001-945E-910A5CBFFEB1}\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "README.md",
    "content": "# mi-scale-exporter\n\nMobile App to export data from Mi Body Composition Scale (works with Mi Scale too) and upload it to Garmin Connect Cloud. It also allows you to upload manually entered body composition data to the Garmin cloud.\n\nInstruction: [https://lswiderski.github.io/mi-scale-exporter/](https://lswiderski.github.io/mi-scale-exporter/)\n\nTested on Oneplus 5T (Android 10) and Mi Body Composition Scale (XMTZC02HM)\n\n## Download\n\n<a href=\"https://play.google.com/store/apps/details?id=com.lukaszswiderski.MiScaleExporter\" target=\"_blank\"><img alt=\"Google Play MiScale Exporter\" height=\"90\" src=\"https://play.google.com/intl/en_US/badges/images/generic/en_badge_web_generic.png\"/></a>\n\n- Google play: https://play.google.com/store/apps/details?id=com.lukaszswiderski.MiScaleExporter\n- APK/AAB installers: https://github.com/lswiderski/mi-scale-exporter/releases\n\n## iOS/iPadOS version\n\nCheck out this web project: https://github.com/lswiderski/WebBodyComposition\n\n## Instruction\n\n- Stand on your scale. Measure yourself. Complete the user form data, Scale Bluetooth address and get data from the scale. Mi Body Composition Scale is active up to 15 min after the measurement. (Bluetooth address can be found in Zepp Life > Profile > My devices > Mi Body Composition Scale > Bluetooth address (hold to copy)).\n\n- If your scale supports \"Weigh small object\" - turn it off\n\n- Then you can review your data and upload it to Garmin Cloud. If you do not have Mi scale and just want to manually insert the data, you can so.\n\n- You can save the Garmin password in this App but you don't have to. Passwords Managers like KeePass2 works well too. If you do not provide a password in the settings, you will be asked for it each time before sending. No password will be saved in app.\n\n- This app support 2FA/MFA codes (since v2.1.0)\n\n- This App pass your data, email and password directly to Garmin Connect Cloud or you can change it to proxy API server and then it sends to Garmin Cloud.\n\n- The Proxy API does not store or log anything, it's just a middleware between this App and Garmin services.\n\n- Proxy API repository: https://github.com/lswiderski/yet-another-garmin-connect-client\n\n- If you afraid of your data, you can host your own API server. Just change the server address in Settings. For now you can use default one: https://frog01-20364.wykr.es\n\n## Diagram of the flow with Web Proxy\n\n```mermaid\nsequenceDiagram\n    participant Mobile App\n    participant Mi Body Composition Scale\n    participant API Endpoint Proxy\n    participant Garmin Cloud\n    Mobile App->>Mi Body Composition Scale: Connect and get data\n    Mi Body Composition Scale-->>Mobile App: Weight and Impedance data\n    loop\n        Mobile App->>Mobile App: Calculate Body Composition\n    end\n    Mobile App->>API Endpoint Proxy: Body Composition data\n    API Endpoint Proxy->>Garmin Cloud: Body Composition data\n    Garmin Cloud-->>API Endpoint Proxy: Result\n    API Endpoint Proxy-->>Mobile App: Result\n\n```\n\n## API Endpoint used in the app ([source](https://github.com/lswiderski/yet-another-garmin-connect-client))\n\n```http\nhttps://frog01-20364.wykr.es\n```\n\n## Diagram of the flow with direct send to Garmin Cloud\n\n```mermaid\nsequenceDiagram\n    participant Mobile App\n    participant Mi Body Composition Scale\n    participant Garmin Cloud\n    Mobile App->>Mi Body Composition Scale: Connect and get data\n    Mi Body Composition Scale-->>Mobile App: Weight and Impedance data\n    loop\n        Mobile App->>Mobile App: Calculate Body Composition\n    end\n    Mobile App->>Garmin Cloud: Body Composition data\n    Garmin Cloud-->>Mobile App: Result\n\n```\n\n## Stack\n\n- MAUI & .NET 7 (C#)\n- Autofac\n- Plugin.BLE - To receive data via Bluetooth from Mi scale\n- Xamarin.Essentials\n- API Backend in C# (YAGCC project)\n\n## Images\n\n- Xiaomi settings (Bluetooth adress - Zepp Life)\n\n![xiaomi settings](https://github.com/lswiderski/mi-scale-exporter/blob/main/resources/img/screenshots/xiaomi.jpg)\n\n- required user data\n\n![required user data](https://github.com/lswiderski/mi-scale-exporter/blob/main/resources/img/screenshots/userdata.jpg)\n\n- settings\n\n![settings](https://github.com/lswiderski/mi-scale-exporter/blob/main/resources/img/screenshots/settings.jpg)\n\n- measure\n\n![measure](https://github.com/lswiderski/mi-scale-exporter/blob/main/resources/img/screenshots/measure.jpg)\n\n- Calculated body composition\n\n![calculated body composition](https://github.com/lswiderski/mi-scale-exporter/blob/main/resources/img/screenshots/bodycomposition.jpg)\n\n- results in Garmin Cloud\n\n![garmin result](https://github.com/lswiderski/mi-scale-exporter/blob/main/resources/img/screenshots/garmin.png)\n\n## Inspiration\n\n- https://github.com/RobertWojtowicz/miscale2garmin\n- https://github.com/davidkroell/bodycomposition\n\n## If you like my work, you can buy me a coffee\n\n<a href=\"https://www.buymeacoffee.com/lukaszswiderski\" target=\"_blank\"><img src=\"https://cdn.buymeacoffee.com/buttons/default-orange.png\" alt=\"Buy Me A Coffee\" height=\"41\" width=\"174\"></a>\n"
  },
  {
    "path": "docs/_config.yml",
    "content": "title: MiScale Exporter\ndescription: Mobile App to export data from Mi Body Composition Scale and upload it to Garmin Connect Cloud\nshow_downloads: true\ngoogle_analytics:\ntheme: jekyll-theme-cayman\n"
  },
  {
    "path": "docs/_includes/head-custom-google-analytics.html",
    "content": "{% if site.google_analytics %}\n<script>\n  (function (i, s, o, g, r, a, m) {\n    i['GoogleAnalyticsObject'] = r;\n    (i[r] =\n      i[r] ||\n      function () {\n        (i[r].q = i[r].q || []).push(arguments);\n      }),\n      (i[r].l = 1 * new Date());\n    (a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);\n    a.async = 1;\n    a.src = g;\n    m.parentNode.insertBefore(a, m);\n  })(\n    window,\n    document,\n    'script',\n    '//www.google-analytics.com/analytics.js',\n    'ga'\n  );\n  ga('create', '{{ site.google_analytics }}', 'auto');\n  ga('send', 'pageview');\n</script>\n{% endif %}\n"
  },
  {
    "path": "docs/_includes/head-custom.html",
    "content": "<!-- start custom head snippets, customize with your own _includes/head-custom.html file -->\n\n<!-- Setup Google Analytics -->\n{% include head-custom-google-analytics.html %}\n\n<!-- You can set your favicon here -->\n<!-- link rel=\"shortcut icon\" type=\"image/x-icon\" href=\"{{ '/favicon.ico' | relative_url }}\" -->\n\n<!-- end custom head snippets -->\n"
  },
  {
    "path": "docs/_layouts/default.html",
    "content": "<!DOCTYPE html>\n<html lang=\"{{ site.lang | default: \"en-US\" }}\">\n  <head>\n    <meta charset=\"UTF-8\">\n\n{% seo %}\n    <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\">\n    <link rel=\"preload\" href=\"https://fonts.googleapis.com/css?family=Open+Sans:400,700&display=swap\" as=\"style\" type=\"text/css\" crossorigin>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <meta name=\"theme-color\" content=\"#157878\">\n    <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\">\n    <link rel=\"stylesheet\" href=\"{{ '/assets/css/style.css?v=' | append: site.github.build_revision | relative_url }}\">\n    {% include head-custom.html %}\n  </head>\n  <body>\n    <a id=\"skip-to-content\" href=\"#content\">Skip to the content.</a>\n\n    <header class=\"page-header\" role=\"banner\">\n      <h1 class=\"project-name\">{{ page.title | default: site.title | default: site.github.repository_name }}</h1>\n      <h2 class=\"project-tagline\">{{ page.description | default: site.description | default: site.github.project_tagline }}</h2>\n      {% if site.github.is_project_page %}\n        <a href=\"{{ site.github.repository_url }}\" class=\"btn\">View on GitHub</a>\n      {% endif %}\n      {% if site.show_downloads %}\n        <a href=\"https://play.google.com/store/apps/details?id=com.lukaszswiderski.MiScaleExporter\" class=\"btn\">Android</a>\n        <a href=\"https://web-body-composition.vercel.app/\" class=\"btn\">Web version (iOS)</a>\n      {% endif %}\n    </header>\n\n    <main id=\"content\" class=\"main-content\" role=\"main\">\n      {{ content }}\n\n      <footer class=\"site-footer\">\n        {% if site.github.is_project_page %}\n          <span class=\"site-footer-owner\"><a href=\"{{ site.github.repository_url }}\">{{ site.github.repository_name }}</a> is maintained by <a href=\"{{ site.github.owner_url }}\">{{ site.github.owner_name }}</a>.</span>\n        {% endif %}\n        <span class=\"site-footer-credits\">This page was generated by <a href=\"https://pages.github.com\">GitHub Pages</a>.</span>\n      </footer>\n    </main>\n  </body>\n</html>"
  },
  {
    "path": "docs/_sass/cayman.scss",
    "content": "// Placeholder file. If your site uses\n//     @import \"{{ site.theme }}\";\n// Then using this theme with jekyll-remote-theme will work fine.\n@import \"jekyll-theme-cayman\";"
  },
  {
    "path": "docs/_sass/jekyll-theme-cayman.scss",
    "content": "@import \"normalize\";\n@import \"rouge-github\";\n@import \"variables\";\n@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,700&display=swap');\n\n@mixin large {\n  @media screen and (min-width: #{$large-breakpoint}) {\n    @content;\n  }\n}\n\n@mixin medium {\n  @media screen and (min-width: #{$medium-breakpoint}) and (max-width: #{$large-breakpoint}) {\n    @content;\n  }\n}\n\n@mixin small {\n  @media screen and (max-width: #{$medium-breakpoint}) {\n    @content;\n  }\n}\n\n* {\n  box-sizing: border-box;\n}\n\nbody {\n  padding: 0;\n  margin: 0;\n  font-family: \"Open Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 16px;\n  line-height: 1.5;\n  color: $body-text-color;\n}\n\n#skip-to-content {\n  height: 1px;\n  width: 1px;\n  position: absolute;\n  overflow: hidden;\n  top: -10px;\n\n  &:focus {\n    position: fixed;\n    top: 10px;\n    left: 10px;\n    height: auto;\n    width: auto;\n    background: invert($body-link-color);\n    outline: thick solid invert($body-link-color);\n  }\n}\n\na {\n  color: $body-link-color;\n  text-decoration: none;\n\n  &:hover {\n    text-decoration: underline;\n  }\n}\n\n.btn {\n  display: inline-block;\n  margin-bottom: 1rem;\n  color: rgba(255, 255, 255, 0.7);\n  background-color: rgba(255, 255, 255, 0.08);\n  border-color: rgba(255, 255, 255, 0.2);\n  border-style: solid;\n  border-width: 1px;\n  border-radius: 0.3rem;\n  transition: color 0.2s, background-color 0.2s, border-color 0.2s;\n\n  &:hover {\n    color: rgba(255, 255, 255, 0.8);\n    text-decoration: none;\n    background-color: rgba(255, 255, 255, 0.2);\n    border-color: rgba(255, 255, 255, 0.3);\n  }\n\n  + .btn {\n    margin-left: 1rem;\n  }\n\n  @include large {\n    padding: 0.75rem 1rem;\n  }\n\n  @include medium {\n    padding: 0.6rem 0.9rem;\n    font-size: 0.9rem;\n  }\n\n  @include small {\n    display: block;\n    width: 100%;\n    padding: 0.75rem;\n    font-size: 0.9rem;\n\n    + .btn {\n      margin-top: 1rem;\n      margin-left: 0;\n    }\n  }\n}\n\n.page-header {\n  color: $header-heading-color;\n  text-align: center;\n  background-color: $header-bg-color;\n  background-image: linear-gradient(120deg, $header-bg-color-secondary, $header-bg-color);\n\n  @include large {\n    padding: 5rem 6rem;\n  }\n\n  @include medium {\n    padding: 3rem 4rem;\n  }\n\n  @include small {\n    padding: 2rem 1rem;\n  }\n}\n\n.project-name {\n  margin-top: 0;\n  margin-bottom: 0.1rem;\n\n  @include large {\n    font-size: 3.25rem;\n  }\n\n  @include medium {\n    font-size: 2.25rem;\n  }\n\n  @include small {\n    font-size: 1.75rem;\n  }\n}\n\n.project-tagline {\n  margin-bottom: 2rem;\n  font-weight: normal;\n  opacity: 0.7;\n\n  @include large {\n    font-size: 1.25rem;\n  }\n\n  @include medium {\n    font-size: 1.15rem;\n  }\n\n  @include small {\n    font-size: 1rem;\n  }\n}\n\n.main-content {\n  word-wrap: break-word;\n\n  :first-child {\n    margin-top: 0;\n  }\n\n  @include large {\n    max-width: 64rem;\n    padding: 2rem 6rem;\n    margin: 0 auto;\n    font-size: 1.1rem;\n  }\n\n  @include medium {\n    padding: 2rem 4rem;\n    font-size: 1.1rem;\n  }\n\n  @include small {\n    padding: 2rem 1rem;\n    font-size: 1rem;\n  }\n  \n  kbd {\n    background-color: #fafbfc;\n    border: 1px solid #c6cbd1;\n    border-bottom-color: #959da5;\n    border-radius: 3px;\n    box-shadow: inset 0 -1px 0 #959da5;\n    color: #444d56;\n    display: inline-block;\n    font-size: 11px;\n    line-height: 10px;\n    padding: 3px 5px;\n    vertical-align: middle;\n  }\n\n  img {\n    max-width: 100%;\n  }\n\n  h1,\n  h2,\n  h3,\n  h4,\n  h5,\n  h6 {\n    margin-top: 2rem;\n    margin-bottom: 1rem;\n    font-weight: normal;\n    color: $section-headings-color;\n  }\n\n  p {\n    margin-bottom: 1em;\n  }\n\n  code {\n    padding: 2px 4px;\n    font-family: Consolas, \"Liberation Mono\", Menlo, Courier, monospace;\n    font-size: 0.9rem;\n    color: $code-text-color;\n    background-color: $code-bg-color;\n    border-radius: 0.3rem;\n  }\n\n  pre {\n    padding: 0.8rem;\n    margin-top: 0;\n    margin-bottom: 1rem;\n    font: 1rem Consolas, \"Liberation Mono\", Menlo, Courier, monospace;\n    color: $code-text-color;\n    word-wrap: normal;\n    background-color: $code-bg-color;\n    border: solid 1px $border-color;\n    border-radius: 0.3rem;\n\n    > code {\n      padding: 0;\n      margin: 0;\n      font-size: 0.9rem;\n      color: $code-text-color;\n      word-break: normal;\n      white-space: pre;\n      background: transparent;\n      border: 0;\n    }\n  }\n\n  .highlight {\n    margin-bottom: 1rem;\n\n    pre {\n      margin-bottom: 0;\n      word-break: normal;\n    }\n  }\n\n  .highlight pre,\n  pre {\n    padding: 0.8rem;\n    overflow: auto;\n    font-size: 0.9rem;\n    line-height: 1.45;\n    border-radius: 0.3rem;\n    -webkit-overflow-scrolling: touch;\n  }\n\n  pre code,\n  pre tt {\n    display: inline;\n    max-width: initial;\n    padding: 0;\n    margin: 0;\n    overflow: initial;\n    line-height: inherit;\n    word-wrap: normal;\n    background-color: transparent;\n    border: 0;\n\n    &:before,\n    &:after {\n      content: normal;\n    }\n  }\n\n  ul,\n  ol {\n    margin-top: 0;\n  }\n\n  blockquote {\n    padding: 0 1rem;\n    margin-left: 0;\n    color: $blockquote-text-color;\n    border-left: 0.3rem solid $border-color;\n\n    > :first-child {\n      margin-top: 0;\n    }\n\n    > :last-child {\n      margin-bottom: 0;\n    }\n  }\n\n  table {\n    display: block;\n    width: 100%;\n    overflow: auto;\n    word-break: normal;\n    word-break: keep-all; // For Firefox to horizontally scroll wider tables.\n    -webkit-overflow-scrolling: touch;\n\n    th {\n      font-weight: bold;\n    }\n\n    th,\n    td {\n      padding: 0.5rem 1rem;\n      border: 1px solid $table-border-color;\n    }\n  }\n\n  dl {\n    padding: 0;\n\n    dt {\n      padding: 0;\n      margin-top: 1rem;\n      font-size: 1rem;\n      font-weight: bold;\n    }\n\n    dd {\n      padding: 0;\n      margin-bottom: 1rem;\n    }\n  }\n\n  hr {\n    height: 2px;\n    padding: 0;\n    margin: 1rem 0;\n    background-color: $hr-border-color;\n    border: 0;\n  }\n}\n\n.site-footer {\n  padding-top: 2rem;\n  margin-top: 2rem;\n  border-top: solid 1px $hr-border-color;\n\n  @include large {\n    font-size: 1rem;\n  }\n\n  @include medium {\n    font-size: 1rem;\n  }\n\n  @include small {\n    font-size: 0.9rem;\n  }\n}\n\n.site-footer-owner {\n  display: block;\n  font-weight: bold;\n}\n\n.site-footer-credits {\n  color: $blockquote-text-color;\n}"
  },
  {
    "path": "docs/_sass/normalize.scss",
    "content": "/*! normalize.css v3.0.2 | MIT License | git.io/normalize */\n\n/**\n * 1. Set default font family to sans-serif.\n * 2. Prevent iOS text size adjust after orientation change, without disabling\n *    user zoom.\n */\n\nhtml {\n  font-family: sans-serif; /* 1 */\n  -ms-text-size-adjust: 100%; /* 2 */\n  -webkit-text-size-adjust: 100%; /* 2 */\n}\n\n/**\n * Remove default margin.\n */\n\nbody {\n  margin: 0;\n}\n\n/* HTML5 display definitions\n   ========================================================================== */\n\n/**\n * Correct `block` display not defined for any HTML5 element in IE 8/9.\n * Correct `block` display not defined for `details` or `summary` in IE 10/11\n * and Firefox.\n * Correct `block` display not defined for `main` in IE 11.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n  display: block;\n}\n\n/**\n * 1. Correct `inline-block` display not defined in IE 8/9.\n * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n */\n\naudio,\ncanvas,\nprogress,\nvideo {\n  display: inline-block; /* 1 */\n  vertical-align: baseline; /* 2 */\n}\n\n/**\n * Prevent modern browsers from displaying `audio` without controls.\n * Remove excess height in iOS 5 devices.\n */\n\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n\n/**\n * Address `[hidden]` styling not present in IE 8/9/10.\n * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.\n */\n\n[hidden],\ntemplate {\n  display: none;\n}\n\n/* Links\n   ========================================================================== */\n\n/**\n * Remove the gray background color from active links in IE 10.\n */\n\na {\n  background-color: transparent;\n}\n\n/**\n * Improve readability when focused and also mouse hovered in all browsers.\n */\n\na:active,\na:hover {\n  outline: 0;\n}\n\n/* Text-level semantics\n   ========================================================================== */\n\n/**\n * Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n */\n\nabbr[title] {\n  border-bottom: 1px dotted;\n}\n\n/**\n * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n */\n\nb,\nstrong {\n  font-weight: bold;\n}\n\n/**\n * Address styling not present in Safari and Chrome.\n */\n\ndfn {\n  font-style: italic;\n}\n\n/**\n * Address variable `h1` font-size and margin within `section` and `article`\n * contexts in Firefox 4+, Safari, and Chrome.\n */\n\nh1 {\n  font-size: 2em;\n  margin: 0.67em 0;\n}\n\n/**\n * Address styling not present in IE 8/9.\n */\n\nmark {\n  background: #ff0;\n  color: #000;\n}\n\n/**\n * Address inconsistent and variable font size in all browsers.\n */\n\nsmall {\n  font-size: 80%;\n}\n\n/**\n * Prevent `sub` and `sup` affecting `line-height` in all browsers.\n */\n\nsub,\nsup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\n/* Embedded content\n   ========================================================================== */\n\n/**\n * Remove border when inside `a` element in IE 8/9/10.\n */\n\nimg {\n  border: 0;\n}\n\n/**\n * Correct overflow not hidden in IE 9/10/11.\n */\n\nsvg:not(:root) {\n  overflow: hidden;\n}\n\n/* Grouping content\n   ========================================================================== */\n\n/**\n * Address margin not present in IE 8/9 and Safari.\n */\n\nfigure {\n  margin: 1em 40px;\n}\n\n/**\n * Address differences between Firefox and other browsers.\n */\n\nhr {\n  box-sizing: content-box;\n  height: 0;\n}\n\n/**\n * Contain overflow in all browsers.\n */\n\npre {\n  overflow: auto;\n}\n\n/**\n * Address odd `em`-unit font size rendering in all browsers.\n */\n\ncode,\nkbd,\npre,\nsamp {\n  font-family: monospace, monospace;\n  font-size: 1em;\n}\n\n/* Forms\n   ========================================================================== */\n\n/**\n * Known limitation: by default, Chrome and Safari on OS X allow very limited\n * styling of `select`, unless a `border` property is set.\n */\n\n/**\n * 1. Correct color not being inherited.\n *    Known issue: affects color of disabled elements.\n * 2. Correct font properties not being inherited.\n * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n */\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n  color: inherit; /* 1 */\n  font: inherit; /* 2 */\n  margin: 0; /* 3 */\n}\n\n/**\n * Address `overflow` set to `hidden` in IE 8/9/10/11.\n */\n\nbutton {\n  overflow: visible;\n}\n\n/**\n * Address inconsistent `text-transform` inheritance for `button` and `select`.\n * All other form control elements do not inherit `text-transform` values.\n * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n * Correct `select` style inheritance in Firefox.\n */\n\nbutton,\nselect {\n  text-transform: none;\n}\n\n/**\n * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n *    and `video` controls.\n * 2. Correct inability to style clickable `input` types in iOS.\n * 3. Improve usability and consistency of cursor style between image-type\n *    `input` and others.\n */\n\nbutton,\nhtml input[type=\"button\"], /* 1 */\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  -webkit-appearance: button; /* 2 */\n  cursor: pointer; /* 3 */\n}\n\n/**\n * Re-set default cursor for disabled elements.\n */\n\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\n\n/**\n * Remove inner padding and border in Firefox 4+.\n */\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  border: 0;\n  padding: 0;\n}\n\n/**\n * Address Firefox 4+ setting `line-height` on `input` using `!important` in\n * the UA stylesheet.\n */\n\ninput {\n  line-height: normal;\n}\n\n/**\n * It's recommended that you don't attempt to style these elements.\n * Firefox's implementation doesn't respect box-sizing, padding, or width.\n *\n * 1. Address box sizing set to `content-box` in IE 8/9/10.\n * 2. Remove excess padding in IE 8/9/10.\n */\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  box-sizing: border-box; /* 1 */\n  padding: 0; /* 2 */\n}\n\n/**\n * Fix the cursor style for Chrome's increment/decrement buttons. For certain\n * `font-size` values of the `input`, it causes the cursor style of the\n * decrement button to change from `default` to `text`.\n */\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto;\n}\n\n/**\n * 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n * 2. Address `box-sizing` set to `border-box` in Safari and Chrome\n *    (include `-moz` to future-proof).\n */\n\ninput[type=\"search\"] {\n  -webkit-appearance: textfield; /* 1 */ /* 2 */\n  box-sizing: content-box;\n}\n\n/**\n * Remove inner padding and search cancel button in Safari and Chrome on OS X.\n * Safari (but not Chrome) clips the cancel button when the search input has\n * padding (and `textfield` appearance).\n */\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\n/**\n * Define consistent border, margin, and padding.\n */\n\nfieldset {\n  border: 1px solid #c0c0c0;\n  margin: 0 2px;\n  padding: 0.35em 0.625em 0.75em;\n}\n\n/**\n * 1. Correct `color` not being inherited in IE 8/9/10/11.\n * 2. Remove padding so people aren't caught out if they zero out fieldsets.\n */\n\nlegend {\n  border: 0; /* 1 */\n  padding: 0; /* 2 */\n}\n\n/**\n * Remove default vertical scrollbar in IE 8/9/10/11.\n */\n\ntextarea {\n  overflow: auto;\n}\n\n/**\n * Don't inherit the `font-weight` (applied by a rule above).\n * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n */\n\noptgroup {\n  font-weight: bold;\n}\n\n/* Tables\n   ========================================================================== */\n\n/**\n * Remove most spacing between table cells.\n */\n\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\ntd,\nth {\n  padding: 0;\n}"
  },
  {
    "path": "docs/_sass/rouge-github.scss",
    "content": ".highlight table td { padding: 5px; }\n.highlight table pre { margin: 0; }\n.highlight .cm {\n  color: #999988;\n  font-style: italic;\n}\n.highlight .cp {\n  color: #999999;\n  font-weight: bold;\n}\n.highlight .c1 {\n  color: #999988;\n  font-style: italic;\n}\n.highlight .cs {\n  color: #999999;\n  font-weight: bold;\n  font-style: italic;\n}\n.highlight .c, .highlight .cd {\n  color: #999988;\n  font-style: italic;\n}\n.highlight .err {\n  color: #a61717;\n  background-color: #e3d2d2;\n}\n.highlight .gd {\n  color: #000000;\n  background-color: #ffdddd;\n}\n.highlight .ge {\n  color: #000000;\n  font-style: italic;\n}\n.highlight .gr {\n  color: #aa0000;\n}\n.highlight .gh {\n  color: #999999;\n}\n.highlight .gi {\n  color: #000000;\n  background-color: #ddffdd;\n}\n.highlight .go {\n  color: #888888;\n}\n.highlight .gp {\n  color: #555555;\n}\n.highlight .gs {\n  font-weight: bold;\n}\n.highlight .gu {\n  color: #aaaaaa;\n}\n.highlight .gt {\n  color: #aa0000;\n}\n.highlight .kc {\n  color: #000000;\n  font-weight: bold;\n}\n.highlight .kd {\n  color: #000000;\n  font-weight: bold;\n}\n.highlight .kn {\n  color: #000000;\n  font-weight: bold;\n}\n.highlight .kp {\n  color: #000000;\n  font-weight: bold;\n}\n.highlight .kr {\n  color: #000000;\n  font-weight: bold;\n}\n.highlight .kt {\n  color: #445588;\n  font-weight: bold;\n}\n.highlight .k, .highlight .kv {\n  color: #000000;\n  font-weight: bold;\n}\n.highlight .mf {\n  color: #009999;\n}\n.highlight .mh {\n  color: #009999;\n}\n.highlight .il {\n  color: #009999;\n}\n.highlight .mi {\n  color: #009999;\n}\n.highlight .mo {\n  color: #009999;\n}\n.highlight .m, .highlight .mb, .highlight .mx {\n  color: #009999;\n}\n.highlight .sb {\n  color: #d14;\n}\n.highlight .sc {\n  color: #d14;\n}\n.highlight .sd {\n  color: #d14;\n}\n.highlight .s2 {\n  color: #d14;\n}\n.highlight .se {\n  color: #d14;\n}\n.highlight .sh {\n  color: #d14;\n}\n.highlight .si {\n  color: #d14;\n}\n.highlight .sx {\n  color: #d14;\n}\n.highlight .sr {\n  color: #009926;\n}\n.highlight .s1 {\n  color: #d14;\n}\n.highlight .ss {\n  color: #990073;\n}\n.highlight .s {\n  color: #d14;\n}\n.highlight .na {\n  color: #008080;\n}\n.highlight .bp {\n  color: #999999;\n}\n.highlight .nb {\n  color: #0086B3;\n}\n.highlight .nc {\n  color: #445588;\n  font-weight: bold;\n}\n.highlight .no {\n  color: #008080;\n}\n.highlight .nd {\n  color: #3c5d5d;\n  font-weight: bold;\n}\n.highlight .ni {\n  color: #800080;\n}\n.highlight .ne {\n  color: #990000;\n  font-weight: bold;\n}\n.highlight .nf {\n  color: #990000;\n  font-weight: bold;\n}\n.highlight .nl {\n  color: #990000;\n  font-weight: bold;\n}\n.highlight .nn {\n  color: #555555;\n}\n.highlight .nt {\n  color: #000080;\n}\n.highlight .vc {\n  color: #008080;\n}\n.highlight .vg {\n  color: #008080;\n}\n.highlight .vi {\n  color: #008080;\n}\n.highlight .nv {\n  color: #008080;\n}\n.highlight .ow {\n  color: #000000;\n  font-weight: bold;\n}\n.highlight .o {\n  color: #000000;\n  font-weight: bold;\n}\n.highlight .w {\n  color: #bbbbbb;\n}\n.highlight {\n  background-color: #f8f8f8;\n}"
  },
  {
    "path": "docs/_sass/variables.scss",
    "content": "// Breakpoints\n$large-breakpoint: 64em !default;\n$medium-breakpoint: 42em !default;\n\n// Headers\n$header-heading-color: #fff !default;\n$header-bg-color: #159957 !default;\n$header-bg-color-secondary: #155799 !default;\n\n// Text\n$section-headings-color: #159957 !default;\n$body-text-color: #606c71 !default;\n$body-link-color: #1e6bb8 !default;\n$blockquote-text-color: #819198 !default;\n\n// Code\n$code-bg-color: #f3f6fa !default;\n$code-text-color: #567482 !default;\n\n// Borders\n$border-color: #dce6f0 !default;\n$table-border-color: #e9ebec !default;\n$hr-border-color: #eff0f1 !default;"
  },
  {
    "path": "docs/index.md",
    "content": "---\nlayout: default\n---\n\nMobile App to export data from Xiaomi Scales:\n\n- Mi Smart Scale\n- [Mi Body Composition Scale 1 and 2](#steps-to-connect-mi-body-compostion-scale-1-and-2)\n- [Mi Body Composition Scale S400](#steps-to-connect-xiaomi-body-composition-scale-s400) (only Android)\n\nand upload it to [Garmin Connect Cloud.](#garmin-connect-upload)\n\nIt also allows you to upload manually entered body composition data to the Garmin cloud.\n\n> [!CAUTION]  \n> This application is not supported or endorsed by Xiaomi or Garmin. So it could stop working at any moment. It is intended for personal use only and is not to be used for financial gain. The creator takes no responsibility for any consequences that may arise from its use.\n\n## If you like my work, you can buy me a coffee\n\n<a href=\"https://www.buymeacoffee.com/lukaszswiderski\" target=\"_blank\"><img src=\"https://cdn.buymeacoffee.com/buttons/default-orange.png\" alt=\"Buy Me A Coffee\" height=\"41\" width=\"174\"></a>\n\n## Steps to Connect Mi Body Compostion Scale 1 and 2:\n\n1. Add Scale to Zepp Life app.\n\n2. You will need the Bluetooth address of the scale. Go to Zepp Life > Profile > My devices > Mi Body Composition Scale > Bluetooth address (hold to copy)\n\n    <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/lswiderski/mi-scale-exporter/blob/main/resources/img/screenshots/xiaomi.jpg\"><img src=\"https://github.com/lswiderski/mi-scale-exporter/raw/main/resources/img/screenshots/xiaomi.jpg\" alt=\"Xiaomi settings\" style=\"width: 400px; margin: auto;\n    display: block;\"></a>\n\n3. If your scale supports \"Weigh small object\" - turn it off\n\n4. Open Settings in MiSCale Exporter. Select Scale Model to Mi Body Compositon Scale 1 / 2 and paste Bluetooth address.\n\n      <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/lswiderski/mi-scale-exporter/blob/main/resources/img/screenshots/userdata.jpg\"><img src=\"https://github.com/lswiderski/mi-scale-exporter/raw/main/resources/img/screenshots/userdata.jpg\" alt=\"MiScale Exporter settings\" style=\"width: 400px; margin: auto; display: block;\"></a>\n\n5. Now it's time for measurement. Stand on your scale. Measure yourself and get data from the scale. Mi Body Composition Scale is active up to 15 min after the measurement.\n\n<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/lswiderski/mi-scale-exporter/blob/main/resources/img/screenshots/measure.jpg\"><img src=\"https://github.com/lswiderski/mi-scale-exporter/raw/main/resources/img/screenshots/measure.jpg\" alt=\"measure\" style=\"width: 400px; margin: auto;\n    display: block;\"></a>\n\n6. These types of scales do not measure body composition. They measure weight and impedance and estimate the result based on those measurements. The exact calculation algorithm is unknown, but with the help of reverse engineers, an approximate one has been achieved, which gives a satisfactory result. However, this means that the final result may differ slightly from that provided by the application. For this calculation proper age, height and sex is needed.\n\n## Steps to Connect Xiaomi Body Composition Scale S400:\n\n1. Add Scale to Xiaomi Home App and do first measurement. You can disable Heart rate measurement to fast up whole process.\n\n2. You will need scale MAC address and BLE Key from Xiaomi Cloud. You can get it on many ways but I recommend 'Xiaomi Cloud Tokens Extractor'\n   Go to  <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/PiotrMachowski/Xiaomi-cloud-tokens-extractor\">https://github.com/PiotrMachowski/Xiaomi-cloud-tokens-extractor</a> and use your preferred way.\n   \n   Find Xiaomi Body Composition Scale S400 on the list of your devices and copy BLE KEY and MAC and save it for later.\n\n   <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/lswiderski/mi-scale-exporter/blob/main/resources/img/screenshots/token_extractor.png\"><img src=\"https://github.com/lswiderski/mi-scale-exporter/raw/main/resources/img/screenshots/token_extractor.png\" alt=\"Xiaomi Cloud Tokens Extractor\" style=\"width: 836px; margin: auto; display: block;\"></a>\n\n3. Now you need to completely kill the app (so that it doesn't run in the background either). Or remove the scale from the list of devices - if you use other devices with Xiaomi Home. The scale will only send the needed data when it is not able to connect to the Xiaomi Home app! Every time when you add Scale as new device to Xiaomi Home new BLE key will be generated. \n\n   <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/lswiderski/mi-scale-exporter/blob/main/resources/img/screenshots/xiaomi_home.png\"><img src=\"https://github.com/lswiderski/mi-scale-exporter/raw/main/resources/img/screenshots/xiaomi_home.png\" alt=\"Xiaomi Homer\" style=\"width: 400px; margin: auto;\n    display: block;\"></a>\n\n4. Now got MiScale Exporter settings, select S400 scale and paste MAC address and BLE Key.\n   \n   <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/lswiderski/mi-scale-exporter/blob/main/resources/img/screenshots/s400_settings.png\"><img src=\"https://github.com/lswiderski/mi-scale-exporter/raw/main/resources/img/screenshots/s400_settings.png\" alt=\"S400 settings\" style=\"width: 400px; margin: auto;\n    display: block;\"></a>\n\n5. The scale only sends data in a short time window at the end of weighing, so it's important to start the measurement before stepping on the scale. The Bluetooth icon should blink. (Watch the video below)\n   \n   [![Watch the video](https://img.youtube.com/vi/HtOZZwnkZHw/0.jpg)](https://www.youtube.com/shorts/HtOZZwnkZHw)\n\n6. These types of scales do not measure body composition. They measure weight and impedance and estimate the result based on those measurements. The scale sends 3 values: Weight, impedance and Heart rate. To receive body composition data, impedance is processed by an algorithm known to be similar to that used by the Mi Body Composition Scale 2 (different from that used by the S400). Because of this, the result may differ from that of the Xiaomi Home app. For this calculation proper age, height and sex is needed.\n\n7. Bear in mind that it is an experimental solution and errors may occur. If you encounter them, please contact me.\n\n## Garmin Connect Upload\n\n1. After successfully retrieving data from the scale, you will be redirected to the Garmin data form.\n\n2. Here you can see the result of your measurement and send it to the Garmin Connect cloud.\n   \n   <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/lswiderski/mi-scale-exporter/blob/main/resources/img/screenshots/bodycomposition.jpg\"><img src=\"https://github.com/lswiderski/mi-scale-exporter/raw/main/resources/img/screenshots/bodycomposition.jpg\" alt=\"calculated body composition\" style=\"width: 400px; margin: auto;\n    display: block;\"></a>\n\n3. If you have set up your email and password in the settings, you do not need to enter anything else here.\n\n4. This app support 2FA/MFA codes. If you use MFA security, you will receive a message asking you to enter a code when you first try to send a message. It should be sent to your email address or as a text message to your phone (depending on your region). Close the message and enter the code in the new MFA field that appears at the bottom of the screen.\n\n5. You don't have to enter the code every time you try to send a message. The returned token will be saved in the app and will be valid for several months.\n\n<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/lswiderski/mi-scale-exporter/blob/main/resources/img/screenshots/garmin.png\"><img src=\"https://github.com/lswiderski/mi-scale-exporter/raw/main/resources/img/screenshots/garmin.png\" alt=\"Garmin results\" style=\"width: 722px; margin: auto;\n    display: block;\"></a>\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/App.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<Application\n    x:Class=\"MiScaleExporter.MAUI.App\"\n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n    xmlns:local=\"clr-namespace:MiScaleExporter.MAUI\"\n    xmlns:converters=\"clr-namespace:MiScaleExporter.MAUI.Converters\">\n    <Application.Resources>\n        <ResourceDictionary>\n            <ResourceDictionary.MergedDictionaries>\n                <ResourceDictionary Source=\"Resources/Styles/Colors.xaml\" />\n                <ResourceDictionary Source=\"Resources/Styles/Styles.xaml\" />\n            </ResourceDictionary.MergedDictionaries>\n            <converters:InvertedBoolConverter x:Key=\"InvertedBoolConverter\" />\n        </ResourceDictionary>\n    </Application.Resources>\n</Application>\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/App.xaml.cs",
    "content": "﻿using Autofac;\nusing Autofac.Extras.CommonServiceLocator;\nusing CommonServiceLocator;\nusing MiScaleExporter.Models;\nusing MiScaleExporter.Services;\nusing MiScaleExporter.MAUI.ViewModels;\nusing IContainer = Autofac.IContainer;\nusing MiScaleExporter.Droid;\nusing System.Globalization;\nusing CommunityToolkit.Maui.Storage;\n\nnamespace MiScaleExporter.MAUI\n{\n    public partial class App : Application\n    {\n        public static IContainer Container;\n        public static BodyComposition BodyComposition;\n        public App()\n        {\n            CultureInfo.DefaultThreadCurrentCulture = Thread.CurrentThread.CurrentCulture;\n            InitializeComponent();\n\n        }\n\n        protected override Window CreateWindow(IActivationState activationState)\n        {\n            // Workaround for: 'Either set MainPage or override CreateWindow.'??\n            if (this.MainPage == null)\n            {\n                AutofacInit();\n                this.MainPage = new AppShell();\n            }\n\n            return base.CreateWindow(activationState);\n        }\n\n        protected override void OnStart()\n        {\n            base.OnStart();\n            AutofacInit();\n            MainPage = new AppShell();\n        }\n\n        protected void AutofacInit()\n        {\n            // Initialize Autofac builder\n            var builder = new ContainerBuilder();\n\n            // Register services\n            builder.RegisterType<Scale>().As<IScale>().InstancePerLifetimeScope();\n            builder.RegisterType<DataInterpreter>().As<IDataInterpreter>().InstancePerLifetimeScope();\n            builder.RegisterType<GarminService>().As<IGarminService>().InstancePerLifetimeScope();\n            builder.RegisterType<ScaleViewModel>().As<IScaleViewModel>().InstancePerLifetimeScope();\n            builder.RegisterType<FormViewModel>().As<IFormViewModel>().InstancePerLifetimeScope();\n            builder.RegisterType<LogService>().As<ILogService>().SingleInstance();\n            builder.RegisterType<SettingsViewModel>().As<ISettingsViewModel>().InstancePerLifetimeScope();\n            builder.RegisterType<AboutViewModel>().AsSelf();\n            builder.RegisterInstance<IFileSaver>(FileSaver.Default).SingleInstance();\n\n            App.Container = builder.Build();\n            ServiceLocator.SetLocatorProvider(() => new AutofacServiceLocator(Container));\n        }\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/AppShell.xaml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<Shell\n    x:Class=\"MiScaleExporter.MAUI.AppShell\"\n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n    xmlns:controls=\"clr-namespace:MiScaleExporter.Controls\"\n    xmlns:local=\"clr-namespace:MiScaleExporter.MAUI.Views\"\n    xmlns:localization=\"clr-namespace:MiScaleExporter.MAUI.Resources.Localization\"\n    FlyoutBackgroundImageAspect=\"AspectFill\"\n    FlyoutHeaderBehavior=\"CollapseOnScroll\">\n\n\n    <Shell.Resources>\n        <ResourceDictionary>\n            <Style x:Key=\"BaseStyle\" TargetType=\"Element\">\n                <Setter Property=\"Shell.BackgroundColor\" Value=\"{StaticResource Primary}\" />\n                <Setter Property=\"Shell.ForegroundColor\" Value=\"White\" />\n                <Setter Property=\"Shell.TitleColor\" Value=\"White\" />\n                <Setter Property=\"Shell.DisabledColor\" Value=\"#B4FFFFFF\" />\n                <Setter Property=\"Shell.UnselectedColor\" Value=\"#95FFFFFF\" />\n                <Setter Property=\"Shell.TabBarBackgroundColor\" Value=\"{StaticResource Primary}\" />\n                <Setter Property=\"Shell.TabBarForegroundColor\" Value=\"White\" />\n                <Setter Property=\"Shell.TabBarUnselectedColor\" Value=\"#95FFFFFF\" />\n                <Setter Property=\"Shell.TabBarTitleColor\" Value=\"White\" />\n            </Style>\n            <Style BasedOn=\"{StaticResource BaseStyle}\" TargetType=\"TabBar\" />\n            <Style BasedOn=\"{StaticResource BaseStyle}\" TargetType=\"FlyoutItem\" />\n\n            <!--\n                Default Styles for all Flyout Items\n                https://docs.microsoft.com/xamarin/xamarin-forms/app-fundamentals/shell/flyout#flyoutitem-and-menuitem-style-classes\n            -->\n            <Style Class=\"FlyoutItemLabelStyle\" TargetType=\"Label\">\n                <Setter Property=\"TextColor\" Value=\"White\" />\n            </Style>\n            <Style\n                ApplyToDerivedTypes=\"True\"\n                Class=\"FlyoutItemLayoutStyle\"\n                TargetType=\"Layout\">\n                <Setter Property=\"VisualStateManager.VisualStateGroups\">\n                    <VisualStateGroupList>\n                        <VisualStateGroup x:Name=\"CommonStates\">\n                            <VisualState x:Name=\"Normal\">\n                                <VisualState.Setters>\n                                    <Setter Property=\"BackgroundColor\" Value=\"{x:OnPlatform UWP=Transparent, iOS=White}\" />\n                                    <Setter TargetName=\"FlyoutItemLabel\" Property=\"Label.TextColor\" Value=\"{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}\" />\n                                </VisualState.Setters>\n                            </VisualState>\n                            <VisualState x:Name=\"Selected\">\n                                <VisualState.Setters>\n                                    <Setter Property=\"BackgroundColor\" Value=\"{StaticResource Primary}\" />\n                                    <Setter TargetName=\"FlyoutItemLabel\" Property=\"Label.TextColor\" Value=\"{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}\" />\n                                </VisualState.Setters>\n                            </VisualState>\n                        </VisualStateGroup>\n                    </VisualStateGroupList>\n                </Setter>\n            </Style>\n\n            <!--\n                Custom Style you can apply to any Flyout Item\n            -->\n            <Style\n                ApplyToDerivedTypes=\"True\"\n                Class=\"MenuItemLayoutStyle\"\n                TargetType=\"Layout\">\n                <Setter Property=\"VisualStateManager.VisualStateGroups\">\n                    <VisualStateGroupList>\n                        <VisualStateGroup x:Name=\"CommonStates\">\n                            <VisualState x:Name=\"Normal\">\n                                <VisualState.Setters>\n                                    <Setter TargetName=\"FlyoutItemLabel\" Property=\"Label.TextColor\" Value=\"{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}\" />\n                                </VisualState.Setters>\n                            </VisualState>\n                        </VisualStateGroup>\n                    </VisualStateGroupList>\n                </Setter>\n            </Style>\n        </ResourceDictionary>\n    </Shell.Resources>\n\n    <Shell.FlyoutHeader>\n        <controls:FlyoutHeader />\n    </Shell.FlyoutHeader>\n\n    <Shell.FlyoutFooter>\n        <controls:FlyoutFooter />\n    </Shell.FlyoutFooter>\n\n\n    <FlyoutItem Title=\"{x:Static localization:AppSnippets.Start}\">\n        <FlyoutItem.Icon>\n            <FontImageSource\n                FontFamily=\"FontAwesome6Solid\"\n                Glyph=\"&#xf05a;\"\n                Size=\"16\"\n                Color=\"{AppThemeBinding Light={StaticResource Black},\n                                        Dark={StaticResource White}}\" />\n        </FlyoutItem.Icon>\n        <ShellContent ContentTemplate=\"{DataTemplate local:AboutPage}\" Route=\"AboutPage\" />\n    </FlyoutItem>\n\n    <FlyoutItem Title=\"{x:Static localization:AppSnippets.MiScale}\">\n        <FlyoutItem.Icon>\n            <FontImageSource\n                FontFamily=\"FontAwesome6Solid\"\n                Glyph=\"&#xf496;\"\n                Size=\"16\"\n                Color=\"{AppThemeBinding Light={StaticResource Black},\n                                        Dark={StaticResource White}}\" />\n        </FlyoutItem.Icon>\n        <ShellContent ContentTemplate=\"{DataTemplate local:ScalePage}\" Route=\"ScalePage\" />\n    </FlyoutItem>\n\n    <FlyoutItem Title=\"{x:Static localization:AppSnippets.GarminForm}\">\n        <FlyoutItem.Icon>\n            <FontImageSource\n                FontFamily=\"FontAwesome6Solid\"\n                Glyph=\"&#xf0ee;\"\n                Size=\"16\"\n                Color=\"{AppThemeBinding Light={StaticResource Black},\n                                        Dark={StaticResource White}}\" />\n        </FlyoutItem.Icon>\n        <ShellContent ContentTemplate=\"{DataTemplate local:FormPage}\" Route=\"FormPage\" />\n    </FlyoutItem>\n\n    <FlyoutItem Title=\"{x:Static localization:AppSnippets.Settings}\">\n        <FlyoutItem.Icon>\n            <FontImageSource\n                FontFamily=\"FontAwesome6Solid\"\n                Glyph=\"&#xf013;\"\n                Size=\"16\"\n                Color=\"{AppThemeBinding Light={StaticResource Black},\n                                        Dark={StaticResource White}}\" />\n        </FlyoutItem.Icon>\n        <ShellContent ContentTemplate=\"{DataTemplate local:SettingPage}\" Route=\"Settings\" />\n    </FlyoutItem>\n    <FlyoutItem Title=\"{x:Static localization:AppSnippets.Help}\">\n        <FlyoutItem.Icon>\n            <FontImageSource\n                FontFamily=\"FontAwesome6Solid\"\n                Glyph=\"&#xf059;\"\n                Size=\"16\"\n                Color=\"{AppThemeBinding Light={StaticResource Black},\n                                        Dark={StaticResource White}}\" />\n        </FlyoutItem.Icon>\n        <ShellContent ContentTemplate=\"{DataTemplate local:HelpPage}\" Route=\"HelpPage\" />\n    </FlyoutItem>\n\n</Shell>\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/AppShell.xaml.cs",
    "content": "﻿namespace MiScaleExporter.MAUI\n{\n    public partial class AppShell : Shell\n    {\n        public AppShell()\n        {\n            InitializeComponent();\n        }\n        private async void OnMenuItemClicked(object sender, EventArgs e)\n        {\n            await Shell.Current.GoToAsync(\"..\");\n        }\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Behaviors/NumericDoubleValidationBehavior.cs",
    "content": "﻿\n\n\nusing MiScaleExporter.MAUI.Utils;\n\nnamespace MiScaleExporter.MAUI.Behaviors;\n\npublic class NumericDoubleValidationBehavior : Behavior<Entry>\n{\n    protected override void OnAttachedTo(Entry entry)\n    {\n        entry.TextChanged += OnEntryTextChanged;\n        base.OnAttachedTo(entry);\n    }\n\n    protected override void OnDetachingFrom(Entry entry)\n    {\n        entry.TextChanged -= OnEntryTextChanged;\n        base.OnDetachingFrom(entry);\n    }\n\n    void OnEntryTextChanged(object sender, TextChangedEventArgs args)\n    {\n        bool isValid = DoubleValueParser.IsValid(args.NewTextValue);\n        var defaultColor = Application.Current.RequestedTheme == AppTheme.Dark ? Color.FromRgb(255, 255, 255) : Color.FromRgb(0, 0, 0);\n        ((Entry)sender).TextColor = isValid ? defaultColor : Color.FromRgb(255, 0, 0);\n    }\n\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Behaviors/NumericIntValidationBehavior.cs",
    "content": "﻿ \n\nnamespace MiScaleExporter.MAUI.Behaviors;\n\npublic class NumericIntValidationBehavior : Behavior<Entry>\n{\n    protected override void OnAttachedTo(Entry entry)\n    {\n        entry.TextChanged += OnEntryTextChanged;\n        base.OnAttachedTo(entry);\n    }\n\n    protected override void OnDetachingFrom(Entry entry)\n    {\n        entry.TextChanged -= OnEntryTextChanged;\n        base.OnDetachingFrom(entry);\n    }\n\n    void OnEntryTextChanged(object sender, TextChangedEventArgs args)\n    {\n        bool isValid = int.TryParse(args.NewTextValue, out _);\n        var defaultColor = Application.Current.RequestedTheme == AppTheme.Dark ? Color.FromRgb(255, 255, 255) : Color.FromRgb(0, 0, 0);\n        ((Entry)sender).TextColor = isValid ? defaultColor : Color.FromRgb(255, 0, 0);\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Controls/FlyoutFooter.xaml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<ContentView\n    x:Class=\"MiScaleExporter.Controls.FlyoutFooter\"\n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n    xmlns:localization=\"clr-namespace:MiScaleExporter.MAUI.Resources.Localization\">\n    <VerticalStackLayout>\n        <Label\n            Margin=\"10\"\n            FontSize=\"Small\"\n            HorizontalOptions=\"Center\"\n            Text=\"{x:Static localization:AppSnippets.CreatedBy}\" />\n    </VerticalStackLayout>\n</ContentView>\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Controls/FlyoutFooter.xaml.cs",
    "content": "namespace MiScaleExporter.Controls;\n\npublic partial class FlyoutFooter : ContentView\n{\n\tpublic FlyoutFooter()\n\t{\n\t\tInitializeComponent();\n\t}\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Controls/FlyoutHeader.xaml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<ContentView xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n             x:Class=\"MiScaleExporter.Controls.FlyoutHeader\">\n    <VerticalStackLayout>\n        <Label \n            Text=\"Mi Scale Exporter\"\n            VerticalOptions=\"Center\" \n            HorizontalOptions=\"Center\"\n            Margin=\"40\"/>\n    </VerticalStackLayout>\n</ContentView>\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Controls/FlyoutHeader.xaml.cs",
    "content": "namespace MiScaleExporter.Controls;\n\npublic partial class FlyoutHeader : ContentView\n{\n\tpublic FlyoutHeader()\n\t{\n\t\tInitializeComponent();\n\t}\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Converters/InvertedBoolConverter.cs",
    "content": "using System.Globalization;\n\nnamespace MiScaleExporter.MAUI.Converters;\n\npublic class InvertedBoolConverter : IValueConverter\n{\n    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)\n    {\n        if (value is bool boolValue)\n        {\n            return !boolValue;\n        }\n        return value;\n    }\n\n    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)\n    {\n        if (value is bool boolValue)\n        {\n            return !boolValue;\n        }\n        return value;\n    }\n}\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/MauiProgram.cs",
    "content": "﻿using CommunityToolkit.Maui;\nusing Plugin.AdMob;\nusing Plugin.AdMob.Configuration;\n\nnamespace MiScaleExporter.MAUI\n{\n    public static class MauiProgram\n    {\n        public static MauiApp CreateMauiApp()\n        {\n            var builder = MauiApp.CreateBuilder();\n            builder.UseMauiApp<App>().ConfigureFonts(fonts =>\n            {\n                fonts.AddFont(\"OpenSans-Regular.ttf\", \"OpenSansRegular\");\n                fonts.AddFont(\"OpenSans-Semibold.ttf\", \"OpenSansSemibold\");\n                fonts.AddFont(\"FontAwesome6Regular.otf\", \"FontAwesome6Regular\");\n                fonts.AddFont(\"FontAwesome6Solid.otf\", \"FontAwesome6Solid\");\n            }).UseMauiCommunityToolkit()\n             .UseAdMob();\n\n#if DEBUG\n            //AdConfig.UseTestAdUnitIds = true;\n\n#endif\n            AdConfig.DefaultBannerAdUnitId = \"ca-app-pub-1938975042085430/4160336701\";\n            return builder.Build();\n        }\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/MiScaleExporter.MAUI.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup>\n\t\t<TargetFrameworks>net9.0-android</TargetFrameworks>\n\t\t<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->\n\t\t<!-- <TargetFrameworks>$(TargetFrameworks);net6.0-tizen</TargetFrameworks> -->\n\t\t<OutputType>Exe</OutputType>\n\t\t<RootNamespace>MiScaleExporter.MAUI</RootNamespace>\n\t\t<UseMaui>true</UseMaui>\n\t\t<SingleProject>true</SingleProject>\n\t\t<ImplicitUsings>enable</ImplicitUsings>\n\t\t\n\t\t<UseNativeHttpHandler>false</UseNativeHttpHandler>\n\t\t<!-- Display name -->\n\t\t<ApplicationTitle>MiScaleExporter.MAUI</ApplicationTitle>\n\n\t\t<!-- App Identifier -->\n\t\t<ApplicationId>com.lukaszswiderski.miscaleexporter.maui</ApplicationId>\n\t\t<ApplicationIdGuid>f67014c4-0bdb-47bd-b669-da42bf0d67c4</ApplicationIdGuid>\n\n\t\t<!-- Versions -->\n\t\t<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>\n\t\t<ApplicationVersion>1</ApplicationVersion>\n\n\t\t<SupportedOSPlatformVersion Condition=\"$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'\">14.2</SupportedOSPlatformVersion>\n\t\t<SupportedOSPlatformVersion Condition=\"$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'\">14.0</SupportedOSPlatformVersion>\n\t\t<SupportedOSPlatformVersion Condition=\"$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'\">23.0</SupportedOSPlatformVersion>\n\t\t<SupportedOSPlatformVersion Condition=\"$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'\">10.0.17763.0</SupportedOSPlatformVersion>\n\t\t<TargetPlatformMinVersion Condition=\"$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'\">10.0.17763.0</TargetPlatformMinVersion>\n\t\t<SupportedOSPlatformVersion Condition=\"$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'\">6.5</SupportedOSPlatformVersion>\n\t</PropertyGroup>\n\n\t<PropertyGroup Condition=\"'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net8.0-android|AnyCPU'\">\n\t  <ApplicationDisplayVersion>2.4.0</ApplicationDisplayVersion>\n\t  <ApplicationVersion>37</ApplicationVersion>\n\t  <AndroidUseAapt2>True</AndroidUseAapt2>\n\t  <AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>\n\t  <AndroidPackageFormat>apk</AndroidPackageFormat>\n\t   <UseNativeHttpHandler Condition=\"'$(UseNativeHttpHandler)' == ''\">true</UseNativeHttpHandler>\n\t  \n\t</PropertyGroup>\n\n\t<PropertyGroup Condition=\"'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net8.0-android|AnyCPU'\">\n\t  <ApplicationDisplayVersion>2.4.0</ApplicationDisplayVersion>\n\t  <ApplicationVersion>37</ApplicationVersion>\n\t  <AndroidPackageFormat>apk</AndroidPackageFormat>\n\t  <AndroidUseAapt2>True</AndroidUseAapt2>\n\t  <AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>\n\t   <UseNativeHttpHandler Condition=\"'$(UseNativeHttpHandler)' == ''\">true</UseNativeHttpHandler>\n\t \n\t</PropertyGroup>\n\n\t<PropertyGroup Condition=\"'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net9.0-android|AnyCPU'\">\n\t  <AndroidPackageFormat>apk</AndroidPackageFormat>\n\t</PropertyGroup>\n\n\t<ItemGroup>\n\t\t<!-- App Icon -->\n\t\t<MauiIcon Include=\"Resources\\AppIcon\\launcher_foreground.png\" Color=\"#FFFFFF\" />\n\t\t<!-- Splash Screen -->\n\t\t<MauiSplashScreen Include=\"Resources\\Splash\\splashscale.png\" BaseSize=\"128,128\" Resize=\"false\" Color=\"#FFFFFF\" />\n\n\t\t<!-- Images -->\n\t\t<MauiImage Include=\"Resources\\Images\\*\" />\n\t\t<MauiImage Update=\"Resources\\Images\\dotnet_bot.svg\" BaseSize=\"168,208\" />\n\n\t\t<!-- Custom Fonts -->\n\t\t<MauiFont Include=\"Resources\\Fonts\\*\" />\n\n\t\t<!-- Raw Assets (also remove the \"Resources\\Raw\" prefix) -->\n\t\t<MauiAsset Include=\"Resources\\Raw\\**\" LogicalName=\"%(RecursiveDir)%(Filename)%(Extension)\" />\n\t</ItemGroup>\n\n\t\n\t<ItemGroup>\n  \t\t<PackageReference Include=\"Microsoft.Maui.Controls\" Version=\"9.0.81\" />\n  \t\t<PackageReference Include=\"Microsoft.Maui.Controls.Compatibility\" Version=\"9.0.81\" />\n\t</ItemGroup>\n\t<ItemGroup>\n\t  <PackageReference Include=\"Autofac\" Version=\"8.3.0\" />\n\t  <PackageReference Include=\"Autofac.Extras.CommonServiceLocator\" Version=\"6.1.0\" />\n\t  <PackageReference Include=\"CommunityToolkit.Maui\" Version=\"12.1.0\" />\n\t  <PackageReference Include=\"MiScaleBodyComposition\" Version=\"1.0.12\" />\n\t  <PackageReference Include=\"Newtonsoft.Json\" Version=\"13.0.3\" />\n\t  <PackageReference Include=\"NLog\" Version=\"5.3.1\" />\n\t  <PackageReference Include=\"NLog.Extensions.Logging\" Version=\"5.3.9\" />\n\t  <PackageReference Include=\"Plugin.AdMob\" Version=\"2.3.2-beta.7\" />\n\t  <PackageReference Include=\"Plugin.BLE\" Version=\"3.2.0-beta.1\" />\n\t  <PackageReference Include=\"Portable.BouncyCastle\" Version=\"1.9.0\" />\n\t  <PackageReference Include=\"YetAnotherGarminConnectClient\" Version=\"0.0.14\" />\n\t</ItemGroup>\n\n\t<ItemGroup>\n\t  <Compile Update=\"Resources\\Localization\\AppSnippets.Designer.cs\">\n\t    <DesignTime>True</DesignTime>\n\t    <AutoGen>True</AutoGen>\n\t    <DependentUpon>AppSnippets.resx</DependentUpon>\n\t  </Compile>\n\t  <Compile Update=\"Views\\AboutPage.xaml.cs\">\n\t    <DependentUpon>%(Filename)</DependentUpon>\n\t  </Compile>\n\t  <Compile Update=\"Views\\FormPage.xaml.cs\">\n\t    <DependentUpon>%(Filename)</DependentUpon>\n\t  </Compile>\n\t  <Compile Update=\"Views\\ScalePage.xaml.cs\">\n\t    <DependentUpon>%(Filename)</DependentUpon>\n\t  </Compile>\n\t  <Compile Update=\"Views\\SettingsPage.xaml.cs\">\n\t    <DependentUpon>%(Filename)</DependentUpon>\n\t  </Compile>\n\t</ItemGroup>\n\n\t<ItemGroup>\n\t  <EmbeddedResource Update=\"Resources\\Localization\\AppSnippets.resx\">\n\t    <Generator>ResXFileCodeGenerator</Generator>\n\t    <LastGenOutput>AppSnippets.Designer.cs</LastGenOutput>\n\t  </EmbeddedResource>\n\t</ItemGroup>\n\n\t<ItemGroup>\n\t  <MauiXaml Update=\"Controls\\FlyoutFooter.xaml\">\n\t    <Generator>MSBuild:Compile</Generator>\n\t  </MauiXaml>\n\t  <MauiXaml Update=\"Controls\\FlyoutHeader.xaml\">\n\t    <Generator>MSBuild:Compile</Generator>\n\t  </MauiXaml>\n\t  <MauiXaml Update=\"Views\\AboutPage.xaml\">\n\t    <Generator>MSBuild:Compile</Generator>\n\t  </MauiXaml>\n\t  <MauiXaml Update=\"Views\\FormPage.xaml\">\n\t    <Generator>MSBuild:Compile</Generator>\n\t  </MauiXaml>\n\t  <MauiXaml Update=\"Views\\HelpPage.xaml\">\n\t    <Generator>MSBuild:Compile</Generator>\n\t  </MauiXaml>\n\t  <MauiXaml Update=\"Views\\ScalePage.xaml\">\n\t    <Generator>MSBuild:Compile</Generator>\n\t  </MauiXaml>\n\t  <MauiXaml Update=\"Views\\SettingsPage.xaml\">\n\t    <Generator>MSBuild:Compile</Generator>\n\t  </MauiXaml>\n\t</ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Models/BodyComposition.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace MiScaleExporter.Models\n{\n    public class BodyComposition\n    {\n        public double BMI { get; set; }\n        public double Weight { get; set; }\n        public double IdealWeight { get; set; }\n        public double MetabolicAge { get; set; }\n        public double ProteinPercentage { get; set; }\n        public double BMR { get; set; }\n        public double Fat { get; set; }\n        public double MuscleMass { get; set; }\n        public double BoneMass { get; set; }\n        public double VisceralFat { get; set; }\n        public int BodyType { get; set; }\n        public double WaterPercentage { get; set; }\n        public bool IsValid { get; set; }\n        public bool HasImpedance { get; set; }\n        public bool IsStabilized { get; set; }\n        public DateTime Date { get; set; }\n        public byte[] ReceivedRawData { get; set; } \n        public string MFACode { get; set; }\n        public string ExternalApiClientId { get; set; }\n        public List<byte[]> RawDataLog { get; set; }\n        public BodyComposition()\n        {\n            RawDataLog = new List<byte[]>();\n        }\n    }\n}\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Models/GarminApiResponse.cs",
    "content": "﻿namespace MiScaleExporter.Models;\n\npublic class GarminApiResponse\n{\n    public bool IsSuccess { get; set; }\n    public string Message { get; set; }\n    public bool MFARequested { get; set; }\n    public string ExternalApiClientId { get; set; }\n    public string AccessToken { get; set; }\n    public string TokenSecret { get; set; }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Models/GarminBodyCompositionRequest.cs",
    "content": "﻿namespace MiScaleExporter.Models;\n\npublic record GarminBodyCompositionRequest\n{\n    public long TimeStamp { get; set; }\n    public double Weight { get; set; }\n    public double PercentFat { get; set; }\n    public double PercentHydration { get; set; }\n    public double BoneMass { get; set; }\n    public double MuscleMass { get; set; }\n    public double VisceralFatRating{ get; set; }\n    public int PhysiqueRating { get; set; }\n    public double MetabolicAge { get; set; }\n    public double BodyMassIndex { get; set; }\n    public string Email { get; set; }\n    public string Password { get; set; }\n    public string ClientID { get; set; }\n    public string MFACode { get; set; }\n    public string AccessToken { get; set; }\n    public string TokenSecret { get; set; }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Models/GarminExternalApiResponse.cs",
    "content": "﻿using YetAnotherGarminConnectClient.Dto;\n\nnamespace MiScaleExporter.Models\n{\n    public record GarminExternalApiResponse\n    {\n        public string ClientId { get; set; }\n        public GarminUploadResult UploadResult { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Models/GarminFitFileCreationResult.cs",
    "content": "﻿namespace MiScaleExporter.Models;\n\n    public class GarminFitFileCreationResult\n    {\n    public bool IsSuccess { get; set; }\n    public string Message { get; set; }\n    public byte[] file { get; set; }\n}\n\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Models/GarminUploadResult.cs",
    "content": "﻿using YetAnotherGarminConnectClient.Dto;\n\nnamespace MiScaleExporter.Models\n{\n    public record GarminUploadResult\n    {\n        public bool IsSuccess { get; set; }\n        public long UploadId { get; set; }\n        public IList<string> Logs { get; set; }\n        public IList<string> ErrorLogs { get; set; }\n        public AuthStatus AuthStatus { get; set; }\n        public bool MFACodeRequested { get; set; }\n        public string? AccessToken { get; set; }\n        public string? TokenSecret { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Models/PreferencesKeys.cs",
    "content": "﻿namespace MiScaleExporter.Models;\n\npublic static class PreferencesKeys\n{\n    public static string UserAge = \"UserAge\";\n    public static string UserBirthDate = \"UserBirthDate\";\n    public static string UseBirthDateMode = \"UseBirthDateMode\";\n    public static string UserHeight = \"UserHeight\";\n    public static string UserSex = \"UserSex\";\n    public static string MiScaleBluetoothAddress = \"MiScaleBluetoothAddress\";\n    public static string GarminUserEmail = \"GarminUserEmail\";\n    public static string GarminUserSavePassword = \"GarminUserSavePassword\";\n    public static string GarminUserPassword = \"GarminUserPassword\";\n    public static string GarminUserAccessToken = \"GarminUserAccessToken\";\n    public static string GarminUserTokenSecret = \"GarminUserTokenSecret\";\n    public static string ApiServerAddressOverride = \"ApiServerAddressOverride\";\n    public static string ScaleType = \"ScaleType\";\n    public static string OneClickScanAndUpload = \"OneClickScanAndUpload\";\n    public static string UseExternalAPI = \"UseExternalAPI\";\n    public static string ShowDebugInfo = \"ShowDebugInfo\";\n    public static string HideAds = \"HideAds\";\n    public static string MuscleMassAsPercentage = \"MuscleMassAsPercentage\";\n    public static string S400Bindkey = \"S400Bindkey\";\n    public static string DisplayWeightInLbs = \"DisplayWeightInLbs\";\n    public static string UseChinaServer = \"UseChinaServer\";\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Models/ScaleMeasurement.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace MiScaleExporter.Models\n{\n    public class ScaleMeasurement : INotifyPropertyChanged \n    {\n\n        private ScaleMeasurement() { }\n        public static ScaleMeasurement Instance { get; } = new ScaleMeasurement();\n\n        private string _weight;\n        public string Weight\n        {\n            get => _weight;\n            set\n            {\n                if (_weight != value)\n                {\n                    _weight = value;\n                    PropertyChanged?.Invoke(this,\n                        new PropertyChangedEventArgs(nameof(Weight)));\n                }\n            }\n        }\n\n        private string _foundScale;\n        public string FoundScale\n        {\n            get => _foundScale;\n            set\n            {\n                if (_foundScale != value)\n                {\n                    _foundScale = value;\n                    PropertyChanged?.Invoke(this,\n                        new PropertyChangedEventArgs(nameof(FoundScale)));\n                }\n            }\n        }\n\n        private string _debugData;\n        public string DebugData\n        {\n            get => _debugData;\n            set\n            {\n                if (_debugData != value)\n                {\n                    _debugData = value;\n                    PropertyChanged?.Invoke(this,\n                        new PropertyChangedEventArgs(nameof(DebugData)));\n                }\n            }\n        }\n\n        private string _rawData;\n        public string RawData\n        {\n            get => _rawData;\n            set\n            {\n                if (_rawData != value)\n                {\n                    _rawData = value;\n                    PropertyChanged?.Invoke(this,\n                        new PropertyChangedEventArgs(nameof(RawData)));\n                }\n            }\n        }\n\n        public event PropertyChangedEventHandler PropertyChanged;\n    }\n}\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Models/ScaleType.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace MiScaleExporter.Models\n{\n    public enum ScaleType : byte\n    {\n        MiBodyCompositionScale = 0,\n        MiSmartScale = 1,\n        S400 = 2,\n    }\n}\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Models/SettingKeys.cs",
    "content": "﻿namespace MiScaleExporter.Models;\n\npublic static class SettingKeys\n{\n    public static string ApiServerAddress = \"https://frog01-20364.wykr.es\";\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Models/Sex.cs",
    "content": "﻿namespace MiScaleExporter.Models\n{\n    public enum Sex : byte\n    {\n        Male = 0,\n        Female = 1,\n    }\n}\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Models/User.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace MiScaleExporter.Models\n{\n    public class User\n    {\n        public int Height { get; set; }\n        public int Age { get; set; }\n        public Sex Sex { get; set; }\n        public ScaleType ScaleType { get; set; }\n        public string BindKey { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Permission/BluetoothConnectPermission.cs",
    "content": "﻿using MiScaleExporter.Permission;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace MiScaleExporter.Droid\n{\n    public class BluetoothConnectPermission : Permissions.BasePlatformPermission, IBluetoothConnectPermission\n    {\n        public override (string androidPermission, bool isRuntime)[] RequiredPermissions => new List<(string androidPermission, bool isRuntime)>\n    {\n        (Android.Manifest.Permission.BluetoothConnect, true),\n        (Android.Manifest.Permission.BluetoothScan, true),\n        (Android.Manifest.Permission.BluetoothAdvertise, true),\n    }.ToArray();\n    }\n}\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Permission/IBluetoothConnectPermission.cs",
    "content": "﻿\nnamespace MiScaleExporter.Permission\n{\n    public interface IBluetoothConnectPermission\n    {\n        Task<PermissionStatus> CheckStatusAsync();\n        Task<PermissionStatus> RequestAsync();\n    }\n}\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Platforms/Android/AndroidManifest.xml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" android:versionCode=\"37\" android:versionName=\"2.4.0\" package=\"com.lukaszswiderski.MiScaleExporter\" android:installLocation=\"auto\">\n\t<uses-permission android:name=\"android.permission.BLUETOOTH\" android:maxSdkVersion=\"30\" />\n\t<uses-permission android:name=\"android.permission.BLUETOOTH_CONNECT\" />\n\t<uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\" android:maxSdkVersion=\"30\" />\n\t<uses-permission android:name=\"android.permission.BLUETOOTH_SCAN\" />\n\t<uses-permission android:name=\"android.permission.BLUETOOTH_ADVERTISE\" />\n\t<uses-permission android:name=\"android.permission.BLUETOOTH_PRIVILEGED\" />\n\t<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />\n\t<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\" />\n\t<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />\n\t<uses-permission android:name=\"android.permission.INTERNET\" />\n\t<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" />\n\t<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />\n\t<uses-permission android:name=\"com.google.android.gms.permission.AD_ID\" />\n\t<uses-feature android:name=\"android.hardware.bluetooth_le\" android:required=\"false\" />\n\t<application android:label=\"MiScale Exporter\" android:usesCleartextTraffic=\"true\" android:theme=\"@style/MainTheme\" android:icon=\"@mipmap/launcher_foreground\" android:allowBackup=\"false\" android:requestLegacyExternalStorage=\"true\">\n\t\t<activity android:name=\"com.google.android.gms.ads.AdActivity\" android:configChanges=\"keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize\" android:theme=\"@android:style/Theme.Translucent\" />\n\t\t<meta-data android:name=\"com.google.android.gms.ads.APPLICATION_ID\" android:value=\"ca-app-pub-1938975042085430~7383010816\" />\n\t</application>\n</manifest>"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Platforms/Android/MainActivity.cs",
    "content": "﻿using Android.App;\nusing Android.Content.PM;\nusing Android.OS;\nusing Android.Runtime;\nusing MiScaleExporter.Droid;\nusing MiScaleExporter.Permission;\n\nnamespace MiScaleExporter.MAUI\n{\n    [Activity(Label = \"MiScale Exporter\", Theme = \"@style/Maui.SplashTheme\", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]\n    public class MainActivity : MauiAppCompatActivity\n    {\n        protected override void OnCreate(Bundle savedInstanceState)\n        {\n            base.OnCreate(savedInstanceState);\n\n            Platform.Init(this, savedInstanceState);\n            DependencyService.Register<IBluetoothConnectPermission, BluetoothConnectPermission>();\n            // LoadApplication(app);\n        }\n        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)\n        {\n            Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);\n\n            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);\n        }\n\n       \n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Platforms/Android/MainApplication.cs",
    "content": "﻿using Android.App;\nusing Android.Runtime;\n\nnamespace MiScaleExporter.MAUI\n{\n    [Application]\n    public class MainApplication : MauiApplication\n    {\n        public MainApplication(IntPtr handle, JniHandleOwnership ownership)\n            : base(handle, ownership)\n        {\n        }\n\n        protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Platforms/Android/Resources/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\t<color name=\"launcher_background\">#FFFFFF</color>\n    <color name=\"colorPrimary\">#007CC3</color>\n    <color name=\"colorPrimaryDark\">#004b76</color>\n    <color name=\"colorAccent\">#007CC3</color>\n</resources>"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Platforms/Android/Resources/values/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<resources>\n\n    <style name=\"MainTheme\" parent=\"MainTheme.Base\">\n    </style>\n  <style name=\"MainTheme.Base\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n      <item name=\"android:windowBackground\">#f2f2f2</item>\n      <item name=\"windowNoTitle\">true</item>\n      <item name=\"windowActionBar\">false</item>\n      <item name=\"windowActionModeOverlay\">true</item>\n      <item name=\"android:textColorPrimary\">#000000</item>\n      <item name=\"android:datePickerDialogTheme\">@style/AppCompatDialogStyle</item>\n    <!-- As of Xamarin.Forms 4.6 the theme has moved into the Forms binary -->\n    <!-- If you want to override anything you can do that here. -->\n    <!-- Underneath are a couple of entries to get you started. -->\n\n    <!-- Set theme colors from https://aka.ms/material-colors -->\n    <!-- colorPrimary is used for the default action bar background -->\n    <!--<item name=\"colorPrimary\">#2196F3</item>-->\n    <!-- colorPrimaryDark is used for the status bar -->\n    <!--<item name=\"colorPrimaryDark\">#1976D2</item>-->\n    <!-- colorAccent is used as the default value for colorControlActivated\n         which is used to tint widgets -->\n   <item name=\"colorAccent\">#2e2e2e</item>\n  </style>\n\n    <style name=\"AppCompatDialogStyle\" parent=\"Theme.AppCompat.Light.Dialog\">\n        <item name=\"colorAccent\">#FF4081</item>\n    </style>\n</resources>"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Platforms/MacCatalyst/AppDelegate.cs",
    "content": "﻿using Foundation;\n\nnamespace MiScaleExporter.MAUI\n{\n    [Register(\"AppDelegate\")]\n    public class AppDelegate : MauiUIApplicationDelegate\n    {\n        protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Platforms/MacCatalyst/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>UIDeviceFamily</key>\n\t<array>\n\t\t<integer>1</integer>\n\t\t<integer>2</integer>\n\t</array>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>arm64</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>XSAppIconAssets</key>\n\t<string>Assets.xcassets/appicon.appiconset</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Platforms/MacCatalyst/Program.cs",
    "content": "﻿using ObjCRuntime;\nusing UIKit;\n\nnamespace MiScaleExporter.MAUI\n{\n    public class Program\n    {\n        // This is the main entry point of the application.\n        static void Main(string[] args)\n        {\n            // if you want to use a different Application Delegate class from \"AppDelegate\"\n            // you can specify it here.\n            UIApplication.Main(args, null, typeof(AppDelegate));\n        }\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Platforms/Tizen/Main.cs",
    "content": "using Microsoft.Maui;\nusing Microsoft.Maui.Hosting;\nusing System;\n\nnamespace MiScaleExporter.MAUI\n{\n    internal class Program : MauiApplication\n    {\n        protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();\n\n        static void Main(string[] args)\n        {\n            var app = new Program();\n            app.Run(args);\n        }\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Platforms/Tizen/tizen-manifest.xml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest package=\"maui-application-id-placeholder\" version=\"0.0.0\" api-version=\"7\" xmlns=\"http://tizen.org/ns/packages\">\n  <profile name=\"common\" />\n  <ui-application appid=\"maui-application-id-placeholder\" exec=\"MiScaleExporter.MAUI.dll\" multiple=\"false\" nodisplay=\"false\" taskmanage=\"true\" type=\"dotnet\" launch_mode=\"single\">\n    <label>maui-application-title-placeholder</label>\n    <icon>maui-appicon-placeholder</icon>\n    <metadata key=\"http://tizen.org/metadata/prefer_dotnet_aot\" value=\"true\" />\n  </ui-application>\n  <shortcut-list />\n  <privileges>\n    <privilege>http://tizen.org/privilege/internet</privilege>\n  </privileges> \n  <dependencies />\n  <provides-appdefined-privileges />\n</manifest>"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Platforms/Windows/App.xaml",
    "content": "﻿<maui:MauiWinUIApplication\n    x:Class=\"MiScaleExporter.MAUI.WinUI.App\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:maui=\"using:Microsoft.Maui\"\n    xmlns:local=\"using:MiScaleExporter.MAUI.WinUI\">\n\n</maui:MauiWinUIApplication>\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Platforms/Windows/App.xaml.cs",
    "content": "﻿using Microsoft.UI.Xaml;\n\n// To learn more about WinUI, the WinUI project structure,\n// and more about our project templates, see: http://aka.ms/winui-project-info.\n\nnamespace MiScaleExporter.MAUI.WinUI\n{\n    /// <summary>\n    /// Provides application-specific behavior to supplement the default Application class.\n    /// </summary>\n    public partial class App : MauiWinUIApplication\n    {\n        /// <summary>\n        /// Initializes the singleton application object.  This is the first line of authored code\n        /// executed, and as such is the logical equivalent of main() or WinMain().\n        /// </summary>\n        public App()\n        {\n            this.InitializeComponent();\n        }\n\n        protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Platforms/Windows/Package.appxmanifest",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Package\n  xmlns=\"http://schemas.microsoft.com/appx/manifest/foundation/windows10\"\n  xmlns:uap=\"http://schemas.microsoft.com/appx/manifest/uap/windows10\"\n  xmlns:rescap=\"http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities\"\n  IgnorableNamespaces=\"uap rescap\">\n\n  <Identity Name=\"maui-package-name-placeholder\" Publisher=\"CN=User Name\" Version=\"0.0.0.0\" />\n\n  <Properties>\n    <DisplayName>$placeholder$</DisplayName>\n    <PublisherDisplayName>User Name</PublisherDisplayName>\n    <Logo>$placeholder$.png</Logo>\n  </Properties>\n\n  <Dependencies>\n    <TargetDeviceFamily Name=\"Windows.Universal\" MinVersion=\"10.0.17763.0\" MaxVersionTested=\"10.0.19041.0\" />\n    <TargetDeviceFamily Name=\"Windows.Desktop\" MinVersion=\"10.0.17763.0\" MaxVersionTested=\"10.0.19041.0\" />\n  </Dependencies>\n\n  <Resources>\n    <Resource Language=\"x-generate\" />\n  </Resources>\n\n  <Applications>\n    <Application Id=\"App\" Executable=\"$targetnametoken$.exe\" EntryPoint=\"$targetentrypoint$\">\n      <uap:VisualElements\n        DisplayName=\"$placeholder$\"\n        Description=\"$placeholder$\"\n        Square150x150Logo=\"$placeholder$.png\"\n        Square44x44Logo=\"$placeholder$.png\"\n        BackgroundColor=\"transparent\">\n        <uap:DefaultTile Square71x71Logo=\"$placeholder$.png\" Wide310x150Logo=\"$placeholder$.png\" Square310x310Logo=\"$placeholder$.png\" />\n        <uap:SplashScreen Image=\"$placeholder$.png\" />\n      </uap:VisualElements>\n    </Application>\n  </Applications>\n\n  <Capabilities>\n    <rescap:Capability Name=\"runFullTrust\" />\n  </Capabilities>\n\n</Package>\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Platforms/Windows/app.manifest",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<assembly manifestVersion=\"1.0\" xmlns=\"urn:schemas-microsoft-com:asm.v1\">\n  <assemblyIdentity version=\"1.0.0.0\" name=\"MiScaleExporter.MAUI.WinUI.app\"/>\n\n  <application xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n    <windowsSettings>\n      <!-- The combination of below two tags have the following effect:\n           1) Per-Monitor for >= Windows 10 Anniversary Update\n           2) System < Windows 10 Anniversary Update\n      -->\n      <dpiAware xmlns=\"http://schemas.microsoft.com/SMI/2005/WindowsSettings\">true/PM</dpiAware>\n      <dpiAwareness xmlns=\"http://schemas.microsoft.com/SMI/2016/WindowsSettings\">PerMonitorV2, PerMonitor</dpiAwareness>\n    </windowsSettings>\n  </application>\n</assembly>\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Platforms/iOS/AppDelegate.cs",
    "content": "﻿using Foundation;\n\nnamespace MiScaleExporter.MAUI\n{\n    [Register(\"AppDelegate\")]\n    public class AppDelegate : MauiUIApplicationDelegate\n    {\n        protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Platforms/iOS/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>UIDeviceFamily</key>\n\t<array>\n\t\t<integer>1</integer>\n\t\t<integer>2</integer>\n\t</array>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>arm64</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>XSAppIconAssets</key>\n\t<string>Assets.xcassets/appicon.appiconset</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Platforms/iOS/Program.cs",
    "content": "﻿using ObjCRuntime;\nusing UIKit;\n\nnamespace MiScaleExporter.MAUI\n{\n    public class Program\n    {\n        // This is the main entry point of the application.\n        static void Main(string[] args)\n        {\n            // if you want to use a different Application Delegate class from \"AppDelegate\"\n            // you can specify it here.\n            UIApplication.Main(args, null, typeof(AppDelegate));\n        }\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Properties/launchSettings.json",
    "content": "{\n  \"profiles\": {\n    \"Windows Machine\": {\n      \"commandName\": \"MsixPackage\",\n      \"nativeDebugging\": false\n    }\n  }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Resources/Localization/AppSnippets.Designer.cs",
    "content": "﻿//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code was generated by a tool.\n//     Runtime Version:4.0.30319.42000\n//\n//     Changes to this file may cause incorrect behavior and will be lost if\n//     the code is regenerated.\n// </auto-generated>\n//------------------------------------------------------------------------------\n\nnamespace MiScaleExporter.MAUI.Resources.Localization {\n    using System;\n    \n    \n    /// <summary>\n    ///   A strongly-typed resource class, for looking up localized strings, etc.\n    /// </summary>\n    // This class was auto-generated by the StronglyTypedResourceBuilder\n    // class via a tool like ResGen or Visual Studio.\n    // To add or remove a member, edit your .ResX file then rerun ResGen\n    // with the /str option, or rebuild your VS project.\n    [global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Resources.Tools.StronglyTypedResourceBuilder\", \"18.0.0.0\")]\n    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\n    internal class AppSnippets {\n        \n        private static global::System.Resources.ResourceManager resourceMan;\n        \n        private static global::System.Globalization.CultureInfo resourceCulture;\n        \n        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute(\"Microsoft.Performance\", \"CA1811:AvoidUncalledPrivateCode\")]\n        internal AppSnippets() {\n        }\n        \n        /// <summary>\n        ///   Returns the cached ResourceManager instance used by this class.\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Resources.ResourceManager ResourceManager {\n            get {\n                if (object.ReferenceEquals(resourceMan, null)) {\n                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager(\"MiScaleExporter.MAUI.Resources.Localization.AppSnippets\", typeof(AppSnippets).Assembly);\n                    resourceMan = temp;\n                }\n                return resourceMan;\n            }\n        }\n        \n        /// <summary>\n        ///   Overrides the current thread's CurrentUICulture property for all\n        ///   resource lookups using this strongly typed resource class.\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Globalization.CultureInfo Culture {\n            get {\n                return resourceCulture;\n            }\n            set {\n                resourceCulture = value;\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to This application is an open source community project and I have no affiliation with Garmin..\n        /// </summary>\n        internal static string AboutGarmin {\n            get {\n                return ResourceManager.GetString(\"AboutGarmin\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Set the bluetooth address of the scale, and your data in the settings. Stand on your scale. Measure yourself. Mi Body Composition Scale is active up to 15 min after the measurement..\n        /// </summary>\n        internal static string AboutMeasureInstruction {\n            get {\n                return ResourceManager.GetString(\"AboutMeasureInstruction\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to The application now supports MFA/2FA security features. If you save credentials in settings, authorization tokens will be remembered and you won&apos;t be asked every time for MFA code..\n        /// </summary>\n        internal static string AboutMFAAndStoringData {\n            get {\n                return ResourceManager.GetString(\"AboutMFAAndStoringData\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Then you can review your data and upload it to Garmin Cloud. If you do not have Mi scale and just want to manually insert the data, you can so..\n        /// </summary>\n        internal static string AboutUpload {\n            get {\n                return ResourceManager.GetString(\"AboutUpload\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Age.\n        /// </summary>\n        internal static string Age {\n            get {\n                return ResourceManager.GetString(\"Age\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Alternate External API Address.\n        /// </summary>\n        internal static string AlternateExternalAPIAddress {\n            get {\n                return ResourceManager.GetString(\"AlternateExternalAPIAddress\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to App Settings.\n        /// </summary>\n        internal static string AppSettings {\n            get {\n                return ResourceManager.GetString(\"AppSettings\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Basal Metabolism (kCal):.\n        /// </summary>\n        internal static string BasalMetabolosimKCal {\n            get {\n                return ResourceManager.GetString(\"BasalMetabolosimKCal\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Bluetooth Address.\n        /// </summary>\n        internal static string BluetoothAddress {\n            get {\n                return ResourceManager.GetString(\"BluetoothAddress\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to BMI.\n        /// </summary>\n        internal static string BMI {\n            get {\n                return ResourceManager.GetString(\"BMI\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Body age (years).\n        /// </summary>\n        internal static string BodyAgeYears {\n            get {\n                return ResourceManager.GetString(\"BodyAgeYears\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Body Fat (%).\n        /// </summary>\n        internal static string BodyFatPercent {\n            get {\n                return ResourceManager.GetString(\"BodyFatPercent\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Body Type.\n        /// </summary>\n        internal static string BodyType {\n            get {\n                return ResourceManager.GetString(\"BodyType\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Bone mass (Lbs).\n        /// </summary>\n        internal static string BoneMassLbs {\n            get {\n                return ResourceManager.GetString(\"BoneMassLbs\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Bone mass (Kg).\n        /// </summary>\n        internal static string BoneMassPercent {\n            get {\n                return ResourceManager.GetString(\"BoneMassPercent\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Buy me a coffee.\n        /// </summary>\n        internal static string BuyMeACoffee {\n            get {\n                return ResourceManager.GetString(\"BuyMeACoffee\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Cancel MFA Request.\n        /// </summary>\n        internal static string CancelMFARequest {\n            get {\n                return ResourceManager.GetString(\"CancelMFARequest\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Cancel Search.\n        /// </summary>\n        internal static string CancelSearch {\n            get {\n                return ResourceManager.GetString(\"CancelSearch\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Created by Lukasz Swiderski 2023.\n        /// </summary>\n        internal static string CreatedBy {\n            get {\n                return ResourceManager.GetString(\"CreatedBy\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Data could not be obtained. try again.\n        /// </summary>\n        internal static string DataCouldNotBeObtained {\n            get {\n                return ResourceManager.GetString(\"DataCouldNotBeObtained\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Do you like this app and would you like to support it?.\n        /// </summary>\n        internal static string DoYouLikeAndWouldYouLikeToSupport {\n            get {\n                return ResourceManager.GetString(\"DoYouLikeAndWouldYouLikeToSupport\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Email.\n        /// </summary>\n        internal static string Email {\n            get {\n                return ResourceManager.GetString(\"Email\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Female.\n        /// </summary>\n        internal static string Female {\n            get {\n                return ResourceManager.GetString(\"Female\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Garmin Body Composition Form.\n        /// </summary>\n        internal static string GarminBodyCompositionForm {\n            get {\n                return ResourceManager.GetString(\"GarminBodyCompositionForm\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Garmin Form.\n        /// </summary>\n        internal static string GarminForm {\n            get {\n                return ResourceManager.GetString(\"GarminForm\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Garmin Settings.\n        /// </summary>\n        internal static string GarminSettings {\n            get {\n                return ResourceManager.GetString(\"GarminSettings\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Generate only .fit file.\n        /// </summary>\n        internal static string GenerateOnlyFitFile {\n            get {\n                return ResourceManager.GetString(\"GenerateOnlyFitFile\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Go to scan.\n        /// </summary>\n        internal static string GoToScan {\n            get {\n                return ResourceManager.GetString(\"GoToScan\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Height.\n        /// </summary>\n        internal static string Height {\n            get {\n                return ResourceManager.GetString(\"Height\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Help.\n        /// </summary>\n        internal static string Help {\n            get {\n                return ResourceManager.GetString(\"Help\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 8. Coffee.\n        /// </summary>\n        internal static string HelpCoffee {\n            get {\n                return ResourceManager.GetString(\"HelpCoffee\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Keep in mind that this is my hobby project. It was created for my inner needs and I believe it may be useful to others as well. I do not receive any compensation for creating and maintaining this project. If you want to support the development or thank me, you can buy me a coffee..\n        /// </summary>\n        internal static string HelpCoffeeDescription {\n            get {\n                return ResourceManager.GetString(\"HelpCoffeeDescription\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 1. How to connect to the scale.\n        /// </summary>\n        internal static string HelpConnect {\n            get {\n                return ResourceManager.GetString(\"HelpConnect\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Set the Bluetooth address of the scale in settings. Set the correct age/height/gender values. Measure yourself. The scale is active for up to 15 minutes after measurement..\n        /// </summary>\n        internal static string HelpConnectDescription {\n            get {\n                return ResourceManager.GetString(\"HelpConnectDescription\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Bluetooth address can be found in Zepp Life &gt; Profile &gt; My devices &gt; Mi Body Composition Scale &gt; Bluetooth address (hold to copy).\n        /// </summary>\n        internal static string HelpConnectDescription2 {\n            get {\n                return ResourceManager.GetString(\"HelpConnectDescription2\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 5. External Api.\n        /// </summary>\n        internal static string HelpExternalApi {\n            get {\n                return ResourceManager.GetString(\"HelpExternalApi\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to External API is used as a proxy for older Android phones (9 or lower). The default address is https://frog01-20364.wykr.es/. You can host your own version of the API and this app will send the data to your system instead of Garmin. Check out the project repository for more information..\n        /// </summary>\n        internal static string HelpExternalApiDescription {\n            get {\n                return ResourceManager.GetString(\"HelpExternalApiDescription\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 7. Feedback &amp; Contact.\n        /// </summary>\n        internal static string HelpFeedback {\n            get {\n                return ResourceManager.GetString(\"HelpFeedback\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to If you found a bug, need a feature or have an idea, share it with me at the project repository..\n        /// </summary>\n        internal static string HelpFeedbackDescription {\n            get {\n                return ResourceManager.GetString(\"HelpFeedbackDescription\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 6. Garmin and Xiaomi.\n        /// </summary>\n        internal static string HelpGarminAndXiaomi {\n            get {\n                return ResourceManager.GetString(\"HelpGarminAndXiaomi\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to This application is an open source community project and I have no affiliation with Garmin or Xiaomi. You use it at your own risk. You can always check out the source code on Github..\n        /// </summary>\n        internal static string HelpGarminAndXiaomiDescription {\n            get {\n                return ResourceManager.GetString(\"HelpGarminAndXiaomiDescription\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 2. How It works.\n        /// </summary>\n        internal static string HelpHowItWorks {\n            get {\n                return ResourceManager.GetString(\"HelpHowItWorks\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to This App pass your data, email and password directly to Garmin Cloud or via external API server. The API does not store or log anything, it&apos;s just a middleware between this App and Garmin services..\n        /// </summary>\n        internal static string HelpHowItWorksDescription {\n            get {\n                return ResourceManager.GetString(\"HelpHowItWorksDescription\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 3. Strange results? (Like 10kg only).\n        /// </summary>\n        internal static string HelpStrangeResults {\n            get {\n                return ResourceManager.GetString(\"HelpStrangeResults\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to If you have the Mi Body Composition Scale 2. Disable the &apos;Weight small object&apos; option in Zepp Life.\n        /// </summary>\n        internal static string HelpStrangeResultsDescription {\n            get {\n                return ResourceManager.GetString(\"HelpStrangeResultsDescription\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to 4. Results different from Zepp Life.\n        /// </summary>\n        internal static string HelpZeppLifeDriference {\n            get {\n                return ResourceManager.GetString(\"HelpZeppLifeDriference\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Please check the age/height/gender parameters - should be identical in both apps. But even then, the values may be slightly different because we do not use the exact algorithm used by Xiaomi, but an alternative open source algorithm..\n        /// </summary>\n        internal static string HelpZeppLifeDriferenceDescription {\n            get {\n                return ResourceManager.GetString(\"HelpZeppLifeDriferenceDescription\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Ideal Weight (Kg):.\n        /// </summary>\n        internal static string IdealWeightKg {\n            get {\n                return ResourceManager.GetString(\"IdealWeightKg\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Ideal Weight (Lbs):.\n        /// </summary>\n        internal static string IdealWeightLbs {\n            get {\n                return ResourceManager.GetString(\"IdealWeightLbs\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Male.\n        /// </summary>\n        internal static string Male {\n            get {\n                return ResourceManager.GetString(\"Male\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to MFA Code.\n        /// </summary>\n        internal static string MFACode {\n            get {\n                return ResourceManager.GetString(\"MFACode\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Mi Body Composition Scale 1 / 2.\n        /// </summary>\n        internal static string MiBodyCompositionScale {\n            get {\n                return ResourceManager.GetString(\"MiBodyCompositionScale\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Mi Scale.\n        /// </summary>\n        internal static string MiScale {\n            get {\n                return ResourceManager.GetString(\"MiScale\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Mi Scale Data.\n        /// </summary>\n        internal static string MiScaleData {\n            get {\n                return ResourceManager.GetString(\"MiScaleData\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Mi Scale Exporter.\n        /// </summary>\n        internal static string MiScaleExporter {\n            get {\n                return ResourceManager.GetString(\"MiScaleExporter\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Mi Smart Scale.\n        /// </summary>\n        internal static string MiSmartScale {\n            get {\n                return ResourceManager.GetString(\"MiSmartScale\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Muscle mass as %.\n        /// </summary>\n        internal static string MuscleMassAsPercentage {\n            get {\n                return ResourceManager.GetString(\"MuscleMassAsPercentage\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Muscle Mass (Kg).\n        /// </summary>\n        internal static string MuscleMassKg {\n            get {\n                return ResourceManager.GetString(\"MuscleMassKg\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Muscle Mass (Lbs).\n        /// </summary>\n        internal static string MuscleMassLbs {\n            get {\n                return ResourceManager.GetString(\"MuscleMassLbs\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Muscle Mass (%).\n        /// </summary>\n        internal static string MuscleMassPer {\n            get {\n                return ResourceManager.GetString(\"MuscleMassPer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Not found.\n        /// </summary>\n        internal static string NotFound {\n            get {\n                return ResourceManager.GetString(\"NotFound\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to OK.\n        /// </summary>\n        internal static string OK {\n            get {\n                return ResourceManager.GetString(\"OK\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to One click - Scan &amp; Upload.\n        /// </summary>\n        internal static string OneClickScanUpload {\n            get {\n                return ResourceManager.GetString(\"OneClickScanUpload\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Open Help.\n        /// </summary>\n        internal static string OpenHelp {\n            get {\n                return ResourceManager.GetString(\"OpenHelp\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Password.\n        /// </summary>\n        internal static string Password {\n            get {\n                return ResourceManager.GetString(\"Password\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Permission to use Bluetooth is required to scan..\n        /// </summary>\n        internal static string PermissionBluetoothRequired {\n            get {\n                return ResourceManager.GetString(\"PermissionBluetoothRequired\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Permission to use Location (Bluetooth) is required to scan..\n        /// </summary>\n        internal static string PermissionLocationRequired {\n            get {\n                return ResourceManager.GetString(\"PermissionLocationRequired\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Problem.\n        /// </summary>\n        internal static string Problem {\n            get {\n                return ResourceManager.GetString(\"Problem\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Protein (%):.\n        /// </summary>\n        internal static string ProteinPercent {\n            get {\n                return ResourceManager.GetString(\"ProteinPercent\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Reset to Default.\n        /// </summary>\n        internal static string ResetToDefault {\n            get {\n                return ResourceManager.GetString(\"ResetToDefault\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Response.\n        /// </summary>\n        internal static string Response {\n            get {\n                return ResourceManager.GetString(\"Response\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Scale Model.\n        /// </summary>\n        internal static string ScaleModel {\n            get {\n                return ResourceManager.GetString(\"ScaleModel\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Scale Settings.\n        /// </summary>\n        internal static string ScaleSettings {\n            get {\n                return ResourceManager.GetString(\"ScaleSettings\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Scanning....\n        /// </summary>\n        internal static string Scanning {\n            get {\n                return ResourceManager.GetString(\"Scanning\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Settings.\n        /// </summary>\n        internal static string Settings {\n            get {\n                return ResourceManager.GetString(\"Settings\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Hide Ads Banner.\n        /// </summary>\n        internal static string SettingsHideAds {\n            get {\n                return ResourceManager.GetString(\"SettingsHideAds\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Sex.\n        /// </summary>\n        internal static string Sex {\n            get {\n                return ResourceManager.GetString(\"Sex\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Show Debug Info during scan.\n        /// </summary>\n        internal static string ShowDebug {\n            get {\n                return ResourceManager.GetString(\"ShowDebug\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Start.\n        /// </summary>\n        internal static string Start {\n            get {\n                return ResourceManager.GetString(\"Start\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Stop Measure.\n        /// </summary>\n        internal static string StopMeasure {\n            get {\n                return ResourceManager.GetString(\"StopMeasure\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Time of measurement.\n        /// </summary>\n        internal static string TimeOfMeasurement {\n            get {\n                return ResourceManager.GetString(\"TimeOfMeasurement\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Uploaded.\n        /// </summary>\n        internal static string Uploaded {\n            get {\n                return ResourceManager.GetString(\"Uploaded\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Uploading....\n        /// </summary>\n        internal static string Uploading {\n            get {\n                return ResourceManager.GetString(\"Uploading\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Upload to Garmin Cloud.\n        /// </summary>\n        internal static string UploadToGarminCloud {\n            get {\n                return ResourceManager.GetString(\"UploadToGarminCloud\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Use External API.\n        /// </summary>\n        internal static string UseExternalAPI {\n            get {\n                return ResourceManager.GetString(\"UseExternalAPI\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Values that will not be sent to the cloud:.\n        /// </summary>\n        internal static string ValuesThatWillNotBeSentToTheCloud {\n            get {\n                return ResourceManager.GetString(\"ValuesThatWillNotBeSentToTheCloud\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Visceral fat.\n        /// </summary>\n        internal static string VisceralFat {\n            get {\n                return ResourceManager.GetString(\"VisceralFat\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Visit the project repository.\n        /// </summary>\n        internal static string VisitProjectRepository {\n            get {\n                return ResourceManager.GetString(\"VisitProjectRepository\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Water (%).\n        /// </summary>\n        internal static string WaterPercent {\n            get {\n                return ResourceManager.GetString(\"WaterPercent\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Weight (Kg).\n        /// </summary>\n        internal static string WeightKg {\n            get {\n                return ResourceManager.GetString(\"WeightKg\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   Looks up a localized string similar to Weight (Lbs).\n        /// </summary>\n        internal static string WeightLbs {\n            get {\n                return ResourceManager.GetString(\"WeightLbs\", resourceCulture);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Resources/Localization/AppSnippets.pl.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"AboutGarmin\" xml:space=\"preserve\">\n    <value>Ta aplikacja jest projektem społeczności open source i nie ma żadnych powiązań z firmą Garmin.</value>\n  </data>\n  <data name=\"AboutMeasureInstruction\" xml:space=\"preserve\">\n    <value>Ustaw w ustawieniach adres bluetooth wagi, oraz swoje dane. Stań na swojej wadze. Zmierz się. Mi Body Composition Scale jest aktywna do 15 min po dokonaniu pomiaru.</value>\n  </data>\n  <data name=\"AboutMFAAndStoringData\" xml:space=\"preserve\">\n    <value>Aplikacja obsługuje teraz funkcje bezpieczeństwa MFA/2FA. Jeśli zapiszesz dane uwierzytelniające w ustawieniach, tokeny autoryzacyjne zostaną zapamiętane i nie będziesz za każdym razem proszony o podanie kodu MFA.</value>\n  </data>\n  <data name=\"AboutUpload\" xml:space=\"preserve\">\n    <value>Następnie możesz przejrzeć swoje dane i przesłać je do Garmin Cloud. Jeśli nie masz wagi Mi Scale i możesz po prostu ręcznie wprowadzić dane i przesłac je do Garmin Connect.</value>\n  </data>\n  <data name=\"Age\" xml:space=\"preserve\">\n    <value>Wiek</value>\n  </data>\n  <data name=\"AlternateExternalAPIAddress\" xml:space=\"preserve\">\n    <value>Alternatywny zewnętrzny adres API</value>\n  </data>\n  <data name=\"AppSettings\" xml:space=\"preserve\">\n    <value>Ustawienia aplikacji</value>\n  </data>\n  <data name=\"BasalMetabolosimKCal\" xml:space=\"preserve\">\n    <value>Metabolizm podstawowy (kCal):</value>\n  </data>\n  <data name=\"BluetoothAddress\" xml:space=\"preserve\">\n    <value>Adres Bluetooth</value>\n  </data>\n  <data name=\"BMI\" xml:space=\"preserve\">\n    <value>BMI</value>\n  </data>\n  <data name=\"BodyAgeYears\" xml:space=\"preserve\">\n    <value>Wiek ciała (w latach)</value>\n  </data>\n  <data name=\"BodyFatPercent\" xml:space=\"preserve\">\n    <value>Tłuszcz w organizmie (%)</value>\n  </data>\n  <data name=\"BodyType\" xml:space=\"preserve\">\n    <value>Typ Ciała</value>\n  </data>\n  <data name=\"BoneMassPercent\" xml:space=\"preserve\">\n    <value>Masa kostna (Kg)</value>\n  </data>\n  <data name=\"BoneMassLbs\" xml:space=\"preserve\">\n    <value>Masa kostna (Lbs)</value>\n  </data>\n  <data name=\"BuyMeACoffee\" xml:space=\"preserve\">\n    <value>Postaw mi kawę</value>\n  </data>\n  <data name=\"CancelMFARequest\" xml:space=\"preserve\">\n    <value>Anuluj MFA</value>\n  </data>\n  <data name=\"CancelSearch\" xml:space=\"preserve\">\n    <value>Anuluj wyszukiwanie</value>\n  </data>\n  <data name=\"CreatedBy\" xml:space=\"preserve\">\n    <value>Stworzone przez Łukasza Świderskiego 2023</value>\n  </data>\n  <data name=\"DataCouldNotBeObtained\" xml:space=\"preserve\">\n    <value>Nie udało się uzyskać danych. Spróbuj ponownie</value>\n  </data>\n  <data name=\"DoYouLikeAndWouldYouLikeToSupport\" xml:space=\"preserve\">\n    <value>Czy podoba Ci się ta aplikacja i chciałbyś ją wesprzeć?</value>\n  </data>\n  <data name=\"Email\" xml:space=\"preserve\">\n    <value>Email</value>\n  </data>\n  <data name=\"Female\" xml:space=\"preserve\">\n    <value>Kobieta</value>\n  </data>\n  <data name=\"GarminBodyCompositionForm\" xml:space=\"preserve\">\n    <value>Formularz składu ciała Garmin</value>\n  </data>\n  <data name=\"GarminForm\" xml:space=\"preserve\">\n    <value>Formularz Garmin</value>\n  </data>\n  <data name=\"GarminSettings\" xml:space=\"preserve\">\n    <value>Ustawienia Garmin</value>\n  </data>\n  <data name=\"GenerateOnlyFitFile\" xml:space=\"preserve\">\n    <value>Generuj tylko plik .fit</value>\n  </data>\n  <data name=\"GoToScan\" xml:space=\"preserve\">\n    <value>Przejdź do skanowania</value>\n  </data>\n  <data name=\"Height\" xml:space=\"preserve\">\n    <value>Wzrost</value>\n  </data>\n  <data name=\"Help\" xml:space=\"preserve\">\n    <value>Pomoc</value>\n  </data>\n  <data name=\"HelpCoffee\" xml:space=\"preserve\">\n    <value>8. Kawa</value>\n  </data>\n  <data name=\"HelpCoffeeDescription\" xml:space=\"preserve\">\n    <value>Należy pamiętać, że jest to mój projekt hobbystyczny. Został on stworzony dla moich wewnętrznych potrzeb i wierzę, że może być przydatny również dla innych. Nie otrzymuję żadnego wynagrodzenia za stworzenie i utrzymanie tego projektu. Jeśli chcesz wesprzeć rozwój lub podziękować mi, możesz postawić mi kawę.</value>\n  </data>\n  <data name=\"HelpConnect\" xml:space=\"preserve\">\n    <value>1. Jak podłączyć się do wagi</value>\n  </data>\n  <data name=\"HelpConnectDescription\" xml:space=\"preserve\">\n    <value>Ustawić adres Bluetooth wagi w ustawieniach. Ustaw prawidłowe wartości wieku/wzrostu/płci. Zmierz się. Waga jest aktywna i wysyła wyniki do 15 minut po pomiarze.</value>\n  </data>\n  <data name=\"HelpConnectDescription2\" xml:space=\"preserve\">\n    <value>Adres Bluetooth można znaleźć w Zepp Life &gt; Profil &gt; Moje urządzenia &gt; Mi Body Composition Scale &gt; Adres Bluetooth (przytrzymaj, aby skopiować)</value>\n  </data>\n  <data name=\"HelpExternalApi\" xml:space=\"preserve\">\n    <value>5. Zewnętrzne Api</value>\n  </data>\n  <data name=\"HelpExternalApiDescription\" xml:space=\"preserve\">\n    <value>Zewnętrzny interfejs API jest używany jako proxy dla starszych telefonów z systemem Android (9 lub niższy). Domyślny adres to https://frog01-20364.wykr.es/. Możesz hostować własną wersję API, a ta aplikacja wyśle dane do twojego systemu zamiast do Garmina. Sprawdź repozytorium projektu, aby uzyskać więcej informacji.</value>\n  </data>\n  <data name=\"HelpFeedback\" xml:space=\"preserve\">\n    <value>7. Informacje zwrotne i kontakt</value>\n  </data>\n  <data name=\"HelpFeedbackDescription\" xml:space=\"preserve\">\n    <value>Jeśli znalazłeś błąd, potrzebujesz jakiejś funkcji lub masz pomysł, podziel się nim ze mną w repozytorium projektu.</value>\n  </data>\n  <data name=\"HelpGarminAndXiaomi\" xml:space=\"preserve\">\n    <value>6. Garmin i Xiaomi</value>\n  </data>\n  <data name=\"HelpGarminAndXiaomiDescription\" xml:space=\"preserve\">\n    <value>Ta aplikacja jest otwarto-źródłowym projektem społeczności i nie ma żadnych powiązań z Garminem lub Xiaomi. Używasz jej na własne ryzyko. Zawsze możesz sprawdzić kod źródłowy na Githubie.</value>\n  </data>\n  <data name=\"HelpHowItWorks\" xml:space=\"preserve\">\n    <value>2. Jak to działa</value>\n  </data>\n  <data name=\"HelpHowItWorksDescription\" xml:space=\"preserve\">\n    <value>Ta aplikacja przekazuje Twoje dane, email i hasło bezpośrednio do Garmin Cloud lub poprzez zewnętrzny serwer API. API nie przechowuje ani nie rejestruje niczego, jest to tylko pośrednikiem pomiędzy aplikacją a usługami firmy Garmin.</value>\n  </data>\n  <data name=\"HelpStrangeResults\" xml:space=\"preserve\">\n    <value>3. Dziwne wyniki? (Np zwraca małe wartości jak 10kg)</value>\n  </data>\n  <data name=\"HelpStrangeResultsDescription\" xml:space=\"preserve\">\n    <value>Jeśli posiadasz Mi Body Composition Scale 2. Wyłącz opcję \"Waż mały obiekt\" w Zepp Life</value>\n  </data>\n  <data name=\"HelpZeppLifeDriference\" xml:space=\"preserve\">\n    <value>4. Wyniki różne od Zepp Life</value>\n  </data>\n  <data name=\"HelpZeppLifeDriferenceDescription\" xml:space=\"preserve\">\n    <value>Sprawdź parametry wieku/wzrostui/płci - powinny być identyczne w obu aplikacjach. Ale nawet wtedy wartości mogą być nieco inne, ponieważ nie używamy dokładnie takiego samego algorytmu jak  Xiaomi, ale alternatywnego algorytmu open source.</value>\n  </data>\n  <data name=\"IdealWeightKg\" xml:space=\"preserve\">\n    <value>Idealna masa ciała (Kg):</value>\n  </data>\n  <data name=\"IdealWeightLbs\" xml:space=\"preserve\">\n    <value>Idealna masa ciała (Lbs):</value>\n  </data>\n  <data name=\"Male\" xml:space=\"preserve\">\n    <value>Mężczyzna</value>\n  </data>\n  <data name=\"MFACode\" xml:space=\"preserve\">\n    <value>Kod MFA</value>\n  </data>\n  <data name=\"MiBodyCompositionScale\" xml:space=\"preserve\">\n    <value>Mi Body Composition Scale 1 / 2</value>\n  </data>\n  <data name=\"MiScale\" xml:space=\"preserve\">\n    <value>Mi Scale</value>\n  </data>\n  <data name=\"MiScaleData\" xml:space=\"preserve\">\n    <value>Dane Mi Scale</value>\n  </data>\n  <data name=\"MiScaleExporter\" xml:space=\"preserve\">\n    <value>Mi Scale Exporter</value>\n  </data>\n  <data name=\"MiSmartScale\" xml:space=\"preserve\">\n    <value>Mi Smart Scale</value>\n  </data>\n  <data name=\"MuscleMassAsPercentage\" xml:space=\"preserve\">\n    <value>Masa mięśniowa jako %</value>\n  </data>\n  <data name=\"MuscleMassKg\" xml:space=\"preserve\">\n    <value>Masa mięśniowa (Kg)</value>\n  </data>\n  <data name=\"MuscleMassLbs\" xml:space=\"preserve\">\n    <value>Masa mięśniowa (Lbs)</value>\n  </data>\n  <data name=\"MuscleMassPer\" xml:space=\"preserve\">\n    <value>Masa mięśniowa (%)</value>\n  </data>\n  <data name=\"NotFound\" xml:space=\"preserve\">\n    <value>Nie znaleziono</value>\n  </data>\n  <data name=\"OK\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n  <data name=\"OneClickScanUpload\" xml:space=\"preserve\">\n    <value>Jedno kliknięcie - skanowanie i przesyłanie</value>\n  </data>\n  <data name=\"OpenHelp\" xml:space=\"preserve\">\n    <value>Otwórz pomoc</value>\n  </data>\n  <data name=\"Password\" xml:space=\"preserve\">\n    <value>Hasło</value>\n  </data>\n  <data name=\"PermissionBluetoothRequired\" xml:space=\"preserve\">\n    <value>Do skanowania wymagana jest zgoda na korzystanie z Bluetooth.</value>\n  </data>\n  <data name=\"PermissionLocationRequired\" xml:space=\"preserve\">\n    <value>Do skanowania wymagane jest pozwolenie na korzystanie z funkcji Lokalizacji (Bluetooth).</value>\n  </data>\n  <data name=\"BluetoothDisabled\" xml:space=\"preserve\">\n    <value>Bluetooth jest wyłączony. Włącz Bluetooth, aby skanować wagę Mi Scale.</value>\n  </data>\n  <data name=\"Problem\" xml:space=\"preserve\">\n    <value>Problem</value>\n  </data>\n  <data name=\"ProteinPercent\" xml:space=\"preserve\">\n    <value>Białko (%):</value>\n  </data>\n  <data name=\"ResetToDefault\" xml:space=\"preserve\">\n    <value>Przywrócenie ustawień domyślnych</value>\n  </data>\n  <data name=\"Response\" xml:space=\"preserve\">\n    <value>Odpowiedź</value>\n  </data>\n  <data name=\"ScaleModel\" xml:space=\"preserve\">\n    <value>Model Wagi</value>\n  </data>\n  <data name=\"ScaleSettings\" xml:space=\"preserve\">\n    <value>Ustawienia wagi</value>\n  </data>\n  <data name=\"Scanning\" xml:space=\"preserve\">\n    <value>Skanowanie...</value>\n  </data>\n  <data name=\"Settings\" xml:space=\"preserve\">\n    <value>Ustawienia</value>\n  </data>\n  <data name=\"SettingsHideAds\" xml:space=\"preserve\">\n    <value>Schowaj reklamy</value>\n  </data>\n  <data name=\"Sex\" xml:space=\"preserve\">\n    <value>Płeć</value>\n  </data>\n  <data name=\"ShowDebug\" xml:space=\"preserve\">\n    <value>Pokaż informacje debug podczas skanowania</value>\n  </data>\n  <data name=\"Start\" xml:space=\"preserve\">\n    <value>Start</value>\n  </data>\n  <data name=\"StopMeasure\" xml:space=\"preserve\">\n    <value>Zatrzymaj pomiar</value>\n  </data>\n  <data name=\"TimeOfMeasurement\" xml:space=\"preserve\">\n    <value>Czas pomiaru</value>\n  </data>\n  <data name=\"Uploaded\" xml:space=\"preserve\">\n    <value>Przesłano</value>\n  </data>\n  <data name=\"Uploading\" xml:space=\"preserve\">\n    <value>Wysyłanie...</value>\n  </data>\n  <data name=\"UploadToGarminCloud\" xml:space=\"preserve\">\n    <value>Prześlij do usługi Garmin Cloud</value>\n  </data>\n  <data name=\"UseExternalAPI\" xml:space=\"preserve\">\n    <value>Użyj zewnętrznego API</value>\n  </data>\n  <data name=\"ValuesThatWillNotBeSentToTheCloud\" xml:space=\"preserve\">\n    <value>Wartości, które nie będą wysyłane do chmury:</value>\n  </data>\n  <data name=\"VisceralFat\" xml:space=\"preserve\">\n    <value>Tłuszcz trzewny</value>\n  </data>\n  <data name=\"VisitProjectRepository\" xml:space=\"preserve\">\n    <value>Odwiedź repozytorium projektu</value>\n  </data>\n  <data name=\"WaterPercent\" xml:space=\"preserve\">\n    <value>Woda (%)</value>\n  </data>\n  <data name=\"WeightKg\" xml:space=\"preserve\">\n    <value>Waga (Kg)</value>\n  </data>\n  <data name=\"WeightLbs\" xml:space=\"preserve\">\n    <value>Waga (Lbs)</value>\n  </data>\n</root>"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Resources/Localization/AppSnippets.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"AboutGarmin\" xml:space=\"preserve\">\n    <value>This application is an open source community project and I have no affiliation with Garmin.</value>\n  </data>\n  <data name=\"AboutMeasureInstruction\" xml:space=\"preserve\">\n    <value>Set the bluetooth address of the scale, and your data in the settings. Stand on your scale. Measure yourself. Mi Body Composition Scale is active up to 15 min after the measurement.</value>\n  </data>\n  <data name=\"AboutMFAAndStoringData\" xml:space=\"preserve\">\n    <value>The application now supports MFA/2FA security features. If you save credentials in settings, authorization tokens will be remembered and you won't be asked every time for MFA code.</value>\n  </data>\n  <data name=\"AboutUpload\" xml:space=\"preserve\">\n    <value>Then you can review your data and upload it to Garmin Cloud. If you do not have Mi scale and just want to manually insert the data, you can so.</value>\n  </data>\n  <data name=\"Age\" xml:space=\"preserve\">\n    <value>Age</value>\n  </data>\n  <data name=\"AlternateExternalAPIAddress\" xml:space=\"preserve\">\n    <value>Alternate External API Address</value>\n  </data>\n  <data name=\"AppSettings\" xml:space=\"preserve\">\n    <value>App Settings</value>\n  </data>\n  <data name=\"BasalMetabolosimKCal\" xml:space=\"preserve\">\n    <value>Basal Metabolism (kCal):</value>\n  </data>\n  <data name=\"BluetoothAddress\" xml:space=\"preserve\">\n    <value>Bluetooth Address</value>\n  </data>\n  <data name=\"BMI\" xml:space=\"preserve\">\n    <value>BMI</value>\n  </data>\n  <data name=\"BodyAgeYears\" xml:space=\"preserve\">\n    <value>Body age (years)</value>\n  </data>\n  <data name=\"BodyFatPercent\" xml:space=\"preserve\">\n    <value>Body Fat (%)</value>\n  </data>\n  <data name=\"BodyType\" xml:space=\"preserve\">\n    <value>Body Type</value>\n  </data>\n  <data name=\"BoneMassPercent\" xml:space=\"preserve\">\n    <value>Bone mass (Kg)</value>\n  </data>\n  <data name=\"BoneMassLbs\" xml:space=\"preserve\">\n    <value>Bone mass (Lbs)</value>\n  </data>\n  <data name=\"BuyMeACoffee\" xml:space=\"preserve\">\n    <value>Buy me a coffee</value>\n  </data>\n  <data name=\"CancelMFARequest\" xml:space=\"preserve\">\n    <value>Cancel MFA Request</value>\n  </data>\n  <data name=\"CancelSearch\" xml:space=\"preserve\">\n    <value>Cancel Search</value>\n  </data>\n  <data name=\"CreatedBy\" xml:space=\"preserve\">\n    <value>Created by Lukasz Swiderski 2023</value>\n  </data>\n  <data name=\"DataCouldNotBeObtained\" xml:space=\"preserve\">\n    <value>Data could not be obtained. try again</value>\n  </data>\n  <data name=\"DoYouLikeAndWouldYouLikeToSupport\" xml:space=\"preserve\">\n    <value>Do you like this app and would you like to support it?</value>\n  </data>\n  <data name=\"Email\" xml:space=\"preserve\">\n    <value>Email</value>\n  </data>\n  <data name=\"Female\" xml:space=\"preserve\">\n    <value>Female</value>\n  </data>\n  <data name=\"GarminBodyCompositionForm\" xml:space=\"preserve\">\n    <value>Garmin Body Composition Form</value>\n  </data>\n  <data name=\"GarminForm\" xml:space=\"preserve\">\n    <value>Garmin Form</value>\n  </data>\n  <data name=\"GarminSettings\" xml:space=\"preserve\">\n    <value>Garmin Settings</value>\n  </data>\n  <data name=\"GenerateOnlyFitFile\" xml:space=\"preserve\">\n    <value>Generate only .fit file</value>\n  </data>\n  <data name=\"GoToScan\" xml:space=\"preserve\">\n    <value>Go to scan</value>\n  </data>\n  <data name=\"Height\" xml:space=\"preserve\">\n    <value>Height</value>\n  </data>\n  <data name=\"Help\" xml:space=\"preserve\">\n    <value>Help</value>\n  </data>\n  <data name=\"HelpCoffee\" xml:space=\"preserve\">\n    <value>8. Coffee</value>\n  </data>\n  <data name=\"HelpCoffeeDescription\" xml:space=\"preserve\">\n    <value>Keep in mind that this is my hobby project. It was created for my inner needs and I believe it may be useful to others as well. I do not receive any compensation for creating and maintaining this project. If you want to support the development or thank me, you can buy me a coffee.</value>\n  </data>\n  <data name=\"HelpConnect\" xml:space=\"preserve\">\n    <value>1. How to connect to the scale</value>\n  </data>\n  <data name=\"HelpConnectDescription\" xml:space=\"preserve\">\n    <value>Set the Bluetooth address of the scale in settings. Set the correct age/height/gender values. Measure yourself. The scale is active for up to 15 minutes after measurement.</value>\n  </data>\n  <data name=\"HelpConnectDescription2\" xml:space=\"preserve\">\n    <value>Bluetooth address can be found in Zepp Life &gt; Profile &gt; My devices &gt; Mi Body Composition Scale &gt; Bluetooth address (hold to copy)</value>\n  </data>\n  <data name=\"HelpExternalApi\" xml:space=\"preserve\">\n    <value>5. External Api</value>\n  </data>\n  <data name=\"HelpExternalApiDescription\" xml:space=\"preserve\">\n    <value>External API is used as a proxy for older Android phones (9 or lower). The default address is https://frog01-20364.wykr.es/. You can host your own version of the API and this app will send the data to your system instead of Garmin. Check out the project repository for more information.</value>\n  </data>\n  <data name=\"HelpFeedback\" xml:space=\"preserve\">\n    <value>7. Feedback &amp; Contact</value>\n  </data>\n  <data name=\"HelpFeedbackDescription\" xml:space=\"preserve\">\n    <value>If you found a bug, need a feature or have an idea, share it with me at the project repository.</value>\n  </data>\n  <data name=\"HelpGarminAndXiaomi\" xml:space=\"preserve\">\n    <value>6. Garmin and Xiaomi</value>\n  </data>\n  <data name=\"HelpGarminAndXiaomiDescription\" xml:space=\"preserve\">\n    <value>This application is an open source community project and I have no affiliation with Garmin or Xiaomi. You use it at your own risk. You can always check out the source code on Github.</value>\n  </data>\n  <data name=\"HelpHowItWorks\" xml:space=\"preserve\">\n    <value>2. How It works</value>\n  </data>\n  <data name=\"HelpHowItWorksDescription\" xml:space=\"preserve\">\n    <value>This App pass your data, email and password directly to Garmin Cloud or via external API server. The API does not store or log anything, it's just a middleware between this App and Garmin services.</value>\n  </data>\n  <data name=\"HelpStrangeResults\" xml:space=\"preserve\">\n    <value>3. Strange results? (Like 10kg only)</value>\n  </data>\n  <data name=\"HelpStrangeResultsDescription\" xml:space=\"preserve\">\n    <value>If you have the Mi Body Composition Scale 2. Disable the 'Weight small object' option in Zepp Life</value>\n  </data>\n  <data name=\"HelpZeppLifeDriference\" xml:space=\"preserve\">\n    <value>4. Results different from Zepp Life</value>\n  </data>\n  <data name=\"HelpZeppLifeDriferenceDescription\" xml:space=\"preserve\">\n    <value>Please check the age/height/gender parameters - should be identical in both apps. But even then, the values may be slightly different because we do not use the exact algorithm used by Xiaomi, but an alternative open source algorithm.</value>\n  </data>\n  <data name=\"IdealWeightKg\" xml:space=\"preserve\">\n    <value>Ideal Weight (Kg):</value>\n  </data>\n  <data name=\"IdealWeightLbs\" xml:space=\"preserve\">\n    <value>Ideal Weight (Lbs):</value>\n  </data>\n  <data name=\"Male\" xml:space=\"preserve\">\n    <value>Male</value>\n  </data>\n  <data name=\"MFACode\" xml:space=\"preserve\">\n    <value>MFA Code</value>\n  </data>\n  <data name=\"MiBodyCompositionScale\" xml:space=\"preserve\">\n    <value>Mi Body Composition Scale 1 / 2</value>\n  </data>\n  <data name=\"MiScale\" xml:space=\"preserve\">\n    <value>Mi Scale</value>\n  </data>\n  <data name=\"MiScaleData\" xml:space=\"preserve\">\n    <value>Mi Scale Data</value>\n  </data>\n  <data name=\"MiScaleExporter\" xml:space=\"preserve\">\n    <value>Mi Scale Exporter</value>\n  </data>\n  <data name=\"MiSmartScale\" xml:space=\"preserve\">\n    <value>Mi Smart Scale</value>\n  </data>\n  <data name=\"MuscleMassAsPercentage\" xml:space=\"preserve\">\n    <value>Muscle mass as %</value>\n  </data>\n  <data name=\"MuscleMassKg\" xml:space=\"preserve\">\n    <value>Muscle Mass (Kg)</value>\n  </data>\n  <data name=\"MuscleMassLbs\" xml:space=\"preserve\">\n    <value>Muscle Mass (Lbs)</value>\n  </data>\n  <data name=\"MuscleMassPer\" xml:space=\"preserve\">\n    <value>Muscle Mass (%)</value>\n  </data>\n  <data name=\"NotFound\" xml:space=\"preserve\">\n    <value>Not found</value>\n  </data>\n  <data name=\"OK\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n  <data name=\"OneClickScanUpload\" xml:space=\"preserve\">\n    <value>One click - Scan &amp; Upload</value>\n  </data>\n  <data name=\"OpenHelp\" xml:space=\"preserve\">\n    <value>Open Help</value>\n  </data>\n  <data name=\"Password\" xml:space=\"preserve\">\n    <value>Password</value>\n  </data>\n  <data name=\"PermissionBluetoothRequired\" xml:space=\"preserve\">\n    <value>Permission to use Bluetooth is required to scan.</value>\n  </data>\n  <data name=\"PermissionLocationRequired\" xml:space=\"preserve\">\n    <value>Permission to use Location (Bluetooth) is required to scan.</value>\n  </data>\n  <data name=\"BluetoothDisabled\" xml:space=\"preserve\">\n    <value>Bluetooth is disabled. Please enable Bluetooth to scan for your Mi Scale.</value>\n  </data>\n  <data name=\"Problem\" xml:space=\"preserve\">\n    <value>Problem</value>\n  </data>\n  <data name=\"ProteinPercent\" xml:space=\"preserve\">\n    <value>Protein (%):</value>\n  </data>\n  <data name=\"ResetToDefault\" xml:space=\"preserve\">\n    <value>Reset to Default</value>\n  </data>\n  <data name=\"Response\" xml:space=\"preserve\">\n    <value>Response</value>\n  </data>\n  <data name=\"ScaleModel\" xml:space=\"preserve\">\n    <value>Scale Model</value>\n  </data>\n  <data name=\"ScaleSettings\" xml:space=\"preserve\">\n    <value>Scale Settings</value>\n  </data>\n  <data name=\"Scanning\" xml:space=\"preserve\">\n    <value>Scanning...</value>\n  </data>\n  <data name=\"Settings\" xml:space=\"preserve\">\n    <value>Settings</value>\n  </data>\n  <data name=\"SettingsHideAds\" xml:space=\"preserve\">\n    <value>Hide Ads Banner</value>\n  </data>\n  <data name=\"Sex\" xml:space=\"preserve\">\n    <value>Sex</value>\n  </data>\n  <data name=\"ShowDebug\" xml:space=\"preserve\">\n    <value>Show Debug Info during scan</value>\n  </data>\n  <data name=\"Start\" xml:space=\"preserve\">\n    <value>Start</value>\n  </data>\n  <data name=\"StopMeasure\" xml:space=\"preserve\">\n    <value>Stop Measure</value>\n  </data>\n  <data name=\"TimeOfMeasurement\" xml:space=\"preserve\">\n    <value>Time of measurement</value>\n  </data>\n  <data name=\"Uploaded\" xml:space=\"preserve\">\n    <value>Uploaded</value>\n  </data>\n  <data name=\"Uploading\" xml:space=\"preserve\">\n    <value>Uploading...</value>\n  </data>\n  <data name=\"UploadToGarminCloud\" xml:space=\"preserve\">\n    <value>Upload to Garmin Cloud</value>\n  </data>\n  <data name=\"UseExternalAPI\" xml:space=\"preserve\">\n    <value>Use External API</value>\n  </data>\n  <data name=\"ValuesThatWillNotBeSentToTheCloud\" xml:space=\"preserve\">\n    <value>Values that will not be sent to the cloud:</value>\n  </data>\n  <data name=\"VisceralFat\" xml:space=\"preserve\">\n    <value>Visceral fat</value>\n  </data>\n  <data name=\"VisitProjectRepository\" xml:space=\"preserve\">\n    <value>Visit the project repository</value>\n  </data>\n  <data name=\"WaterPercent\" xml:space=\"preserve\">\n    <value>Water (%)</value>\n  </data>\n  <data name=\"WeightKg\" xml:space=\"preserve\">\n    <value>Weight (Kg)</value>\n  </data>\n  <data name=\"WeightLbs\" xml:space=\"preserve\">\n    <value>Weight (Lbs)</value>\n  </data>\n</root>"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Resources/Raw/AboutAssets.txt",
    "content": "﻿Any raw assets you want to be deployed with your application can be placed in\nthis directory (and child directories). Deployment of the asset to your application\nis automatically handled by the following `MauiAsset` Build Action within your `.csproj`.\n\n\t<MauiAsset Include=\"Resources\\Raw\\**\" LogicalName=\"%(RecursiveDir)%(Filename)%(Extension)\" />\n\nThese files will be deployed with you package and will be accessible using Essentials:\n\n\tasync Task LoadMauiAsset()\n\t{\n\t\tusing var stream = await FileSystem.OpenAppPackageFileAsync(\"AboutAssets.txt\");\n\t\tusing var reader = new StreamReader(stream);\n\n\t\tvar contents = reader.ReadToEnd();\n\t}\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Resources/Styles/Colors.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<?xaml-comp compile=\"true\" ?>\n<ResourceDictionary xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\" xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\">\n\n    <Color x:Key=\"Primary\">#007CC3</Color>\n    <Color x:Key=\"Secondary\">#DFD8F7</Color>\n    <Color x:Key=\"Tertiary\">#004b76</Color>\n    <Color x:Key=\"White\">White</Color>\n    <Color x:Key=\"Black\">Black</Color>\n    <Color x:Key=\"Gray100\">#E1E1E1</Color>\n    <Color x:Key=\"Gray200\">#C8C8C8</Color>\n    <Color x:Key=\"Gray300\">#ACACAC</Color>\n    <Color x:Key=\"Gray400\">#919191</Color>\n    <Color x:Key=\"Gray500\">#6E6E6E</Color>\n    <Color x:Key=\"Gray600\">#404040</Color>\n    <Color x:Key=\"Gray900\">#212121</Color>\n    <Color x:Key=\"Gray950\">#141414</Color>\n    <Color x:Key=\"Gray\">#6E6E6E</Color>\n    <Color x:Key=\"DarkRed\">DarkRed</Color>\n    <SolidColorBrush x:Key=\"PrimaryBrush\" Color=\"{StaticResource Primary}\" />\n    <SolidColorBrush x:Key=\"SecondaryBrush\" Color=\"{StaticResource Secondary}\" />\n    <SolidColorBrush x:Key=\"TertiaryBrush\" Color=\"{StaticResource Tertiary}\" />\n    <SolidColorBrush x:Key=\"WhiteBrush\" Color=\"{StaticResource White}\" />\n    <SolidColorBrush x:Key=\"BlackBrush\" Color=\"{StaticResource Black}\" />\n    <SolidColorBrush x:Key=\"Gray100Brush\" Color=\"{StaticResource Gray100}\" />\n    <SolidColorBrush x:Key=\"Gray200Brush\" Color=\"{StaticResource Gray200}\" />\n    <SolidColorBrush x:Key=\"Gray300Brush\" Color=\"{StaticResource Gray300}\" />\n    <SolidColorBrush x:Key=\"Gray400Brush\" Color=\"{StaticResource Gray400}\" />\n    <SolidColorBrush x:Key=\"Gray500Brush\" Color=\"{StaticResource Gray500}\" />\n    <SolidColorBrush x:Key=\"Gray600Brush\" Color=\"{StaticResource Gray600}\" />\n    <SolidColorBrush x:Key=\"Gray900Brush\" Color=\"{StaticResource Gray900}\" />\n    <SolidColorBrush x:Key=\"Gray950Brush\" Color=\"{StaticResource Gray950}\" />\n\n    <Color x:Key=\"Yellow100Accent\">#F7B548</Color>\n    <Color x:Key=\"Yellow200Accent\">#FFD590</Color>\n    <Color x:Key=\"Yellow300Accent\">#FFE5B9</Color>\n    <Color x:Key=\"Cyan100Accent\">#28C2D1</Color>\n    <Color x:Key=\"Cyan200Accent\">#7BDDEF</Color>\n    <Color x:Key=\"Cyan300Accent\">#C3F2F4</Color>\n    <Color x:Key=\"Blue100Accent\">#3E8EED</Color>\n    <Color x:Key=\"Blue200Accent\">#72ACF1</Color>\n    <Color x:Key=\"Blue300Accent\">#A7CBF6</Color>\n\n</ResourceDictionary>"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Resources/Styles/Styles.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<?xaml-comp compile=\"true\" ?>\n<ResourceDictionary xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\" xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\">\n    <Style TargetType=\"ActivityIndicator\">\n        <Setter Property=\"Color\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n    </Style>\n\n    <Style TargetType=\"IndicatorView\">\n        <Setter Property=\"IndicatorColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}\" />\n        <Setter Property=\"SelectedIndicatorColor\" Value=\"{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray100}}\" />\n    </Style>\n\n    <Style TargetType=\"Border\">\n        <Setter Property=\"Stroke\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}\" />\n        <Setter Property=\"StrokeShape\" Value=\"Rectangle\" />\n        <Setter Property=\"StrokeThickness\" Value=\"1\" />\n    </Style>\n\n    <Style TargetType=\"BoxView\">\n        <Setter Property=\"Color\" Value=\"{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}\" />\n    </Style>\n\n    <Style TargetType=\"Button\">\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Primary}}\" />\n        <Setter Property=\"BackgroundColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\" />\n        <Setter Property=\"FontSize\" Value=\"14\" />\n        <Setter Property=\"CornerRadius\" Value=\"8\" />\n        <Setter Property=\"Padding\" Value=\"14,10\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}\" />\n                            <Setter Property=\"BackgroundColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"CheckBox\">\n        <Setter Property=\"Color\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"Color\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"DatePicker\">\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}\" />\n        <Setter Property=\"BackgroundColor\" Value=\"Transparent\" />\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\" />\n        <Setter Property=\"FontSize\" Value=\"14\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"Editor\">\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}\" />\n        <Setter Property=\"BackgroundColor\" Value=\"Transparent\" />\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\" />\n        <Setter Property=\"FontSize\" Value=\"14\" />\n        <Setter Property=\"PlaceholderColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"Entry\">\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}\" />\n        <Setter Property=\"BackgroundColor\" Value=\"Transparent\" />\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\" />\n        <Setter Property=\"FontSize\" Value=\"14\" />\n        <Setter Property=\"PlaceholderColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"Frame\">\n        <Setter Property=\"HasShadow\" Value=\"False\" />\n        <Setter Property=\"BorderColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}\" />\n        <Setter Property=\"CornerRadius\" Value=\"8\" />\n    </Style>\n\n    <Style TargetType=\"ImageButton\">\n        <Setter Property=\"Opacity\" Value=\"1\" />\n        <Setter Property=\"BorderColor\" Value=\"Transparent\" />\n        <Setter Property=\"BorderWidth\" Value=\"0\" />\n        <Setter Property=\"CornerRadius\" Value=\"0\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"Opacity\" Value=\"0.5\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"Label\">\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}\" />\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\" />\n        <Setter Property=\"FontSize\" Value=\"14\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"ListView\">\n        <Setter Property=\"SeparatorColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}\" />\n        <Setter Property=\"RefreshControlColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}\" />\n    </Style>\n\n    <Style TargetType=\"Picker\">\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}\" />\n        <Setter Property=\"TitleColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}\" />\n        <Setter Property=\"BackgroundColor\" Value=\"Transparent\" />\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\" />\n        <Setter Property=\"FontSize\" Value=\"14\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                            <Setter Property=\"TitleColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"ProgressBar\">\n        <Setter Property=\"ProgressColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"ProgressColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"RadioButton\">\n        <Setter Property=\"Background\" Value=\"Transparent\" />\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}\" />\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\" />\n        <Setter Property=\"FontSize\" Value=\"14\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"RefreshView\">\n        <Setter Property=\"RefreshColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}\" />\n    </Style>\n\n    <Style TargetType=\"SearchBar\">\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}\" />\n        <Setter Property=\"PlaceholderColor\" Value=\"{StaticResource Gray500}\" />\n        <Setter Property=\"CancelButtonColor\" Value=\"{StaticResource Gray500}\" />\n        <Setter Property=\"BackgroundColor\" Value=\"Transparent\" />\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\" />\n        <Setter Property=\"FontSize\" Value=\"14\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                            <Setter Property=\"PlaceholderColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"SearchHandler\">\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}\" />\n        <Setter Property=\"PlaceholderColor\" Value=\"{StaticResource Gray500}\" />\n        <Setter Property=\"BackgroundColor\" Value=\"Transparent\" />\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\" />\n        <Setter Property=\"FontSize\" Value=\"14\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                            <Setter Property=\"PlaceholderColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"Shadow\">\n        <Setter Property=\"Radius\" Value=\"15\" />\n        <Setter Property=\"Opacity\" Value=\"0.5\" />\n        <Setter Property=\"Brush\" Value=\"{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}\" />\n        <Setter Property=\"Offset\" Value=\"10,10\" />\n    </Style>\n\n    <Style TargetType=\"Slider\">\n        <Setter Property=\"MinimumTrackColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n        <Setter Property=\"MaximumTrackColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}\" />\n        <Setter Property=\"ThumbColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"MinimumTrackColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                            <Setter Property=\"MaximumTrackColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                            <Setter Property=\"ThumbColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"SwipeItem\">\n        <Setter Property=\"BackgroundColor\" Value=\"{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}\" />\n    </Style>\n\n    <Style TargetType=\"Switch\">\n        <Setter Property=\"OnColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n        <Setter Property=\"ThumbColor\" Value=\"{StaticResource White}\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"OnColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                            <Setter Property=\"ThumbColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                    <VisualState x:Name=\"On\">\n                        <VisualState.Setters>\n                            <Setter Property=\"OnColor\" Value=\"{AppThemeBinding Light={StaticResource Secondary}, Dark={StaticResource Gray200}}\" />\n                            <Setter Property=\"ThumbColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                    <VisualState x:Name=\"Off\">\n                        <VisualState.Setters>\n                            <Setter Property=\"ThumbColor\" Value=\"{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style TargetType=\"TimePicker\">\n        <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}\" />\n        <Setter Property=\"Background\" Value=\"Transparent\" />\n        <Setter Property=\"FontFamily\" Value=\"OpenSansRegular\" />\n        <Setter Property=\"FontSize\" Value=\"14\" />\n        <Setter Property=\"VisualStateManager.VisualStateGroups\">\n            <VisualStateGroupList>\n                <VisualStateGroup x:Name=\"CommonStates\">\n                    <VisualState x:Name=\"Normal\" />\n                    <VisualState x:Name=\"Disabled\">\n                        <VisualState.Setters>\n                            <Setter Property=\"TextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}\" />\n                        </VisualState.Setters>\n                    </VisualState>\n                </VisualStateGroup>\n            </VisualStateGroupList>\n        </Setter>\n    </Style>\n\n    <Style ApplyToDerivedTypes=\"True\" TargetType=\"Page\">\n        <Setter Property=\"Padding\" Value=\"0\" />\n        <Setter Property=\"BackgroundColor\" Value=\"{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}\" />\n    </Style>\n\n    <Style ApplyToDerivedTypes=\"True\" TargetType=\"Shell\">\n        <Setter Property=\"Shell.BackgroundColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource Gray950}}\" />\n        <Setter Property=\"Shell.ForegroundColor\" Value=\"{OnPlatform WinUI={StaticResource Primary}, Default={StaticResource White}}\" />\n        <Setter Property=\"Shell.TitleColor\" Value=\"{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}\" />\n        <Setter Property=\"Shell.DisabledColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}\" />\n        <Setter Property=\"Shell.UnselectedColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray200}}\" />\n        <Setter Property=\"Shell.NavBarHasShadow\" Value=\"False\" />\n        <Setter Property=\"Shell.TabBarBackgroundColor\" Value=\"{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}\" />\n        <Setter Property=\"Shell.TabBarForegroundColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n        <Setter Property=\"Shell.TabBarTitleColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n        <Setter Property=\"Shell.TabBarUnselectedColor\" Value=\"{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}\" />\n    </Style>\n\n    <Style TargetType=\"NavigationPage\">\n        <Setter Property=\"BarBackgroundColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource Gray950}}\" />\n        <Setter Property=\"BarTextColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}\" />\n        <Setter Property=\"IconColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}\" />\n    </Style>\n\n    <Style TargetType=\"TabbedPage\">\n        <Setter Property=\"BarBackgroundColor\" Value=\"{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Gray950}}\" />\n        <Setter Property=\"BarTextColor\" Value=\"{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}\" />\n        <Setter Property=\"UnselectedTabColor\" Value=\"{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}\" />\n        <Setter Property=\"SelectedTabColor\" Value=\"{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}\" />\n    </Style>\n\n</ResourceDictionary>\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Services/DataInterpreter.cs",
    "content": "﻿using MiScaleBodyComposition.Contracts;\nusing MiScaleExporter.Models;\n\nnamespace MiScaleExporter.Services\n{\n    public class DataInterpreter : IDataInterpreter\n    {\n        private void ValidateAesKey(string aesKey)\n        {\n            if (string.IsNullOrEmpty(aesKey) || aesKey.Length != 32)\n            {\n                throw new ArgumentException(\"AES key must be a 32-character hexadecimal string.\");\n            }\n        }\n        private void ValidateBluetoothAddress(string btAddress)\n        {\n            if (string.IsNullOrEmpty(btAddress) || btAddress.Length != 17 || !btAddress.All(c => char.IsLetterOrDigit(c) || c == ':'))\n            {\n                throw new ArgumentException(\"Bluetooth address must be a valid 17-character string in the format XX:XX:XX:XX:XX:XX.\");\n            }\n        }\n\n        public BodyComposition ComputeData(byte[] data, User _user, string btAddress)\n        {\n\n            var user = new MiScaleBodyComposition.User(_user.Height, _user.Age, (MiScaleBodyComposition.Sex)(byte)_user.Sex);\n            switch (_user.ScaleType)\n            {\n                case ScaleType.MiBodyCompositionScale:\n\n                    var miBodyCompositionScale = new MiScaleBodyComposition.MiScale();\n\n                    var isStabilized = miBodyCompositionScale.Istabilized(data, user);\n                    var hasImpedance = miBodyCompositionScale.HasImpedance(data, user);\n\n                    if (data.Length > 13)\n                    {\n                        data = data.Skip(data.Length - 13).ToArray();\n                    }\n\n                    if (isStabilized)\n                    {\n                        var bc = miBodyCompositionScale.GetBodyComposition(data, user, true);\n                        var bodyComposition = new BodyComposition\n                        {\n                            Weight = bc.Weight,\n                            BMI = bc.BMI,\n                            ProteinPercentage = bc.ProteinPercentage,\n                            IdealWeight = bc.IdealWeight,\n                            BMR = bc.BMR,\n                            BoneMass = bc.BoneMass,\n                            Fat = bc.Fat,\n                            MetabolicAge = bc.MetabolicAge,\n                            MuscleMass = bc.MuscleMass,\n                            VisceralFat = bc.VisceralFat,\n                            WaterPercentage = bc.Water,\n                            BodyType = bc.BodyType,\n                            HasImpedance = hasImpedance,\n                            IsStabilized = isStabilized,\n                            Date = bc.Date,\n\n                        };\n                        return bodyComposition;\n                    }\n                    else\n                    {\n                        var bodyComposition = new BodyComposition\n                        {\n                            Weight = GetWeight(data),\n                            HasImpedance = hasImpedance,\n                            IsStabilized = isStabilized,\n                        };\n                        return bodyComposition;\n                    }\n                case ScaleType.MiSmartScale:\n                    var legacyMiscale = new MiScaleBodyComposition.LegacyMiScale();\n\n                    if (legacyMiscale.Istabilized(data))\n                    {\n                        var legacyResult = legacyMiscale.GetWeight(data, _user.Height, true);\n\n                        var bodyComposition = new BodyComposition\n                        {\n                            Weight = legacyResult.Weight,\n                            BMI = legacyResult.BMI,\n                            Date = legacyResult.Date,\n                            IsStabilized = true\n                        };\n\n                        return bodyComposition;\n                    }\n                    else\n                    {\n                        return null;\n                    }\n                case ScaleType.S400:\n\n                    if(data.Length == 26)\n                    {\n                        this.ValidateAesKey(_user.BindKey);\n                        this.ValidateBluetoothAddress(btAddress);\n\n                        var s400Scale = new MiScaleBodyComposition.S400Scale();\n                        var s400Result = s400Scale.GetBodyComposition(user, new S400InputData\n                        {\n                            Data = data,\n                            AesKey = _user.BindKey,\n                            MacOriginal = btAddress,\n                        });\n                        \n                        if (s400Result != null)\n                        {\n                            var bodyComposition = new BodyComposition\n                            {\n                                Weight = s400Result.Weight,\n                                BMI = s400Result.BMI,\n                                ProteinPercentage = s400Result.ProteinPercentage,\n                                IdealWeight = s400Result.IdealWeight,\n                                BMR = s400Result.BMR,\n                                BoneMass = s400Result.BoneMass,\n                                Fat = s400Result.Fat,\n                                MetabolicAge = s400Result.MetabolicAge,\n                                MuscleMass = s400Result.MuscleMass,\n                                VisceralFat = s400Result.VisceralFat,\n                                WaterPercentage = s400Result.Water,\n                                BodyType = s400Result.BodyType,\n                                HasImpedance = true,\n                                IsStabilized = true,\n                                Date = s400Result.Date,\n\n                            };\n                            return bodyComposition;\n\n                        }\n                    }\n                    var emptyBC = new BodyComposition\n                    {\n                        Weight = 0,\n                        HasImpedance = false,\n                        IsStabilized = false,\n                    };\n                    return emptyBC;\n\n                default:\n                    throw new NotImplementedException();\n            }\n        }\n\n        private double GetWeight(byte[] data)\n        {\n            return (double)(((data[12] & 0xFF) << 8) | (data[11] & 0xFF)) * 0.005;\n        }\n    }\n}\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Services/GarminService.cs",
    "content": "﻿using System;\nusing System.IO;\nusing System.Net;\nusing System.Net.Http;\nusing System.Net.Http.Headers;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Android.Net;\nusing Microsoft.Extensions.Logging;\nusing MiScaleExporter.Models;\nusing Newtonsoft.Json;\nusing NLog;\nusing NLog.Extensions.Logging;\nusing Xamarin.Android.Net;\nusing YetAnotherGarminConnectClient;\nusing YetAnotherGarminConnectClient.Dto.Garmin.Fit;\n\nnamespace MiScaleExporter.Services;\n\npublic class GarminService : IGarminService\n{\n    private HttpClient _httpClient;\n    private ILogService _logService;\n    private Microsoft.Extensions.Logging.ILogger _logger;\n    private IClient _garminClient;\n\n    public GarminService(ILogService logService)\n    {\n        _logService = logService;\n        var configuration = LogService.CreateLogger();\n        using (ILoggerFactory factory = LoggerFactory.Create(builder =>\n        builder.AddNLog(configuration))\n    )\n        {\n            _logger = factory.CreateLogger<GarminService>();\n        }\n\n        System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;\n\n        if (DeviceInfo.Platform == DevicePlatform.Android)\n        {\n            _httpClient = new HttpClient(new AndroidMessageHandler())\n            {\n                Timeout = TimeSpan.FromMinutes(5),\n                DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrHigher,\n                DefaultRequestVersion = HttpVersion.Version11,\n\n            };\n        }\n        else\n        {\n            _httpClient = new HttpClient()\n            {\n                Timeout = TimeSpan.FromMinutes(5),\n            };\n        }\n\n    }\n\n    public async Task<GarminApiResponse> UploadAsync(BodyComposition bodyComposition, DateTime time, CredentialsData credencials)\n    {\n\n        if (DeviceInfo.Platform == DevicePlatform.Android) //Older android versions do not support TLS 1.3, so force to use external api for them\n        {\n            if (DeviceInfo.Version.Major < 10)\n            {\n                Preferences.Set(PreferencesKeys.UseExternalAPI, true);\n            }\n        }\n        if (Preferences.Get(PreferencesKeys.UseExternalAPI, false))\n        {\n            return await UploadViaExternalAPIAsync(bodyComposition, time, credencials);\n        }\n        else\n        {\n            return await UploadViaDirectCallToGarminAsync(bodyComposition, time, credencials);\n        }\n    }\n\n    private async Task<GarminApiResponse> UploadViaDirectCallToGarminAsync(BodyComposition bodyComposition, DateTime time, CredentialsData credencials)\n    {\n        var result = new GarminApiResponse();\n        try\n        {\n            var userProfileSettings = new UserProfileSettings\n            {\n                Age = Preferences.Get(PreferencesKeys.UserAge, 25),\n                Height = Preferences.Get(PreferencesKeys.UserHeight, 170),\n            };\n\n            var scaleDTO = new GarminWeightScaleDTO\n            {\n                TimeStamp = time,\n                Weight = Convert.ToSingle(bodyComposition.Weight),\n                PercentFat = Convert.ToSingle(bodyComposition.Fat),\n                PercentHydration = Convert.ToSingle(bodyComposition.WaterPercentage),\n                BoneMass = Convert.ToSingle(bodyComposition.BoneMass),\n                MuscleMass = Convert.ToSingle(bodyComposition.MuscleMass),\n                VisceralFatRating = Convert.ToByte(bodyComposition.VisceralFat),\n                VisceralFatMass = Convert.ToSingle(bodyComposition.VisceralFat),\n                PhysiqueRating = Convert.ToByte(bodyComposition.BodyType),\n                MetabolicAge = Convert.ToByte(bodyComposition.MetabolicAge),\n                BodyMassIndex = Convert.ToSingle(bodyComposition.BMI),\n            };\n\n            if (string.IsNullOrEmpty(bodyComposition.MFACode))\n            {\n                var useChinaServer = Preferences.Get(PreferencesKeys.UseChinaServer, false);\n                var garminServer = useChinaServer \n                    ? YetAnotherGarminConnectClient.Dto.GarminServer.CHINA \n                    : YetAnotherGarminConnectClient.Dto.GarminServer.GLOBAL;\n                _garminClient = await ClientFactory.Create(garminServer);\n            }\n\n            var garminApiReponse = await _garminClient.UploadWeight(scaleDTO, userProfileSettings, credencials, bodyComposition.MFACode);\n            var logs = LogService.GetLogs();\n            var errorlogs = LogService.GetErrorLogs();\n\n            result.IsSuccess = garminApiReponse.IsSuccess;\n            result.MFARequested = garminApiReponse.MFACodeRequested;\n            result.AccessToken = garminApiReponse.AccessToken;\n            result.TokenSecret = garminApiReponse.TokenSecret;\n\n            if (result.MFARequested)\n            {\n                result.Message = \"Please provide MFA/2FA Code\";\n            }\n\n            if (!result.IsSuccess && !result.MFARequested)\n            {\n                var errorMessage = garminApiReponse?.ErrorLogs?.FirstOrDefault() ?? errorlogs?.FirstOrDefault() ?? \"Error\";\n                throw new Exception(errorMessage);\n            }\n            return result;\n        }\n        catch (Exception ex)\n        {\n            var logs = LogService.GetLogs();\n            var errorlogs = LogService.GetErrorLogs();\n            _logService.LogError(ex?.Message);\n            result.Message = ex.Message;\n            return result;\n        }\n\n    }\n\n    public async Task<GarminFitFileCreationResult> GenerateFitFileAsync(BodyComposition bodyComposition, DateTime time)\n    {\n        var result = new GarminFitFileCreationResult();\n        try\n        {\n            var userProfileSettings = new UserProfileSettings\n            {\n                Age = Preferences.Get(PreferencesKeys.UserAge, 25),\n                Height = Preferences.Get(PreferencesKeys.UserHeight, 170),\n            };\n\n            var scaleDTO = new GarminWeightScaleDTO\n            {\n                TimeStamp = time,\n                Weight = Convert.ToSingle(bodyComposition.Weight),\n                PercentFat = Convert.ToSingle(bodyComposition.Fat),\n                PercentHydration = Convert.ToSingle(bodyComposition.WaterPercentage),\n                BoneMass = Convert.ToSingle(bodyComposition.BoneMass),\n                MuscleMass = Convert.ToSingle(bodyComposition.MuscleMass),\n                VisceralFatRating = Convert.ToByte(bodyComposition.VisceralFat),\n                VisceralFatMass = Convert.ToSingle(bodyComposition.VisceralFat),\n                PhysiqueRating = Convert.ToByte(bodyComposition.BodyType),\n                MetabolicAge = Convert.ToByte(bodyComposition.MetabolicAge),\n                BodyMassIndex = Convert.ToSingle(bodyComposition.BMI),\n               \n            };\n\n            _garminClient = await ClientFactory.Create();\n\n            var file = _garminClient.GenerateWeightFitFile(scaleDTO, userProfileSettings);\n            var logs = LogService.GetLogs();\n            var errorlogs = LogService.GetErrorLogs();\n\n            if(errorlogs.Count > 0)\n            {\n                result.Message = string.Join(Environment.NewLine, errorlogs);\n            }\n            result.IsSuccess = file != null;\n            result.file = file;\n            return result;\n        }\n        catch (Exception ex)\n        {\n            var logs = LogService.GetLogs();\n            var errorlogs = LogService.GetErrorLogs();\n            _logService.LogError(ex?.Message);\n            result.Message = ex.Message;\n            return result;\n        }\n\n    }\n\n    private async Task<GarminApiResponse> UploadViaExternalAPIAsync(BodyComposition bodyComposition, DateTime time, CredentialsData credencials)\n    {\n        var unixTime = ((DateTimeOffset)time).ToUnixTimeSeconds();\n        var request = new GarminBodyCompositionRequest\n        {\n            Email = credencials.Email,\n            Password = credencials.Password,\n            AccessToken = credencials.AccessToken,\n            TokenSecret = credencials.TokenSecret,\n            Weight = bodyComposition.Weight,\n            BoneMass = bodyComposition.BoneMass,\n            MuscleMass = bodyComposition.MuscleMass,\n            MetabolicAge = bodyComposition.MetabolicAge,\n            PercentFat = bodyComposition.Fat,\n            VisceralFatRating = bodyComposition.VisceralFat,\n            BodyMassIndex = bodyComposition.BMI,\n            PercentHydration = bodyComposition.WaterPercentage,\n            PhysiqueRating = bodyComposition.BodyType,\n            TimeStamp = unixTime,\n        };\n\n        if (!string.IsNullOrEmpty(bodyComposition.ExternalApiClientId))\n        {\n            request.MFACode = bodyComposition.MFACode;\n            request.ClientID = bodyComposition.ExternalApiClientId;\n        }\n        return await UploadToGarminCloud(request);\n    }\n\n    private async Task<GarminApiResponse> UploadToGarminCloud(GarminBodyCompositionRequest request)\n    {\n        var result = new GarminApiResponse();\n        try\n        {\n            var dataAsString = JsonConvert.SerializeObject(request);\n            var content = new StringContent(dataAsString, Encoding.UTF8, \"application/json\");\n\n            var response = await PostAsync(\"/upload\", content);\n\n            using (var stream = await response.Content.ReadAsStreamAsync())\n            using (var reader = new StreamReader(stream))\n            {\n                var message = await reader.ReadToEndAsync();\n                if (response.IsSuccessStatusCode)\n                {\n                    var apiResponse = JsonConvert.DeserializeObject<GarminExternalApiResponse>(message);\n\n                    result.AccessToken = apiResponse?.UploadResult?.AccessToken;\n                    result.TokenSecret = apiResponse?.UploadResult?.TokenSecret;\n\n                    if (apiResponse?.UploadResult?.AuthStatus == YetAnotherGarminConnectClient.Dto.AuthStatus.MFARedirected)\n                    {\n                        result.Message = \"Please provide MFA/2FA Code\";\n                        result.MFARequested = true;\n                        result.ExternalApiClientId = apiResponse.ClientId;\n                        return result;\n                    }\n                }\n\n                result.ExternalApiClientId = null;\n                result.IsSuccess = response.IsSuccessStatusCode;\n                result.Message = message;\n\n                return result;\n            }\n        }\n        catch (Exception ex)\n        {\n            _logService.LogError(ex.Message);\n            result.Message = ex.Message;\n            return result;\n        }\n    }\n\n    private async Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content)\n    {\n        var baseAddress = Preferences.Get(PreferencesKeys.ApiServerAddressOverride, SettingKeys.ApiServerAddress);\n        var response = await _httpClient.PostAsync($\"{baseAddress}{requestUri}\", content);\n        return response;\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Services/IDataInterpreter.cs",
    "content": "﻿using MiScaleExporter.Models;\n\nnamespace MiScaleExporter.Services\n{\n    public interface IDataInterpreter\n    {\n        BodyComposition ComputeData(byte[] data, User _user, string btAddress);\n    }\n}\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Services/IGarminService.cs",
    "content": "﻿using System;\nusing System.Threading.Tasks;\nusing MiScaleExporter.Models;\nusing YetAnotherGarminConnectClient.Dto.Garmin.Fit;\n\nnamespace MiScaleExporter.Services;\n\npublic interface IGarminService\n{\n    Task<GarminApiResponse> UploadAsync(BodyComposition bodyComposition, DateTime time, CredentialsData credencials);\n    Task<GarminFitFileCreationResult> GenerateFitFileAsync(BodyComposition bodyComposition, DateTime time);\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Services/ILogService.cs",
    "content": "﻿using System.Reflection;\n\nnamespace MiScaleExporter.Services;\n\npublic interface ILogService\n{\n    void LogDebug(string message);\n    void LogError(string message);\n    void LogFatal(string message);\n    void LogInfo(string message);\n    void LogWarning(string message);\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Services/IScale.cs",
    "content": "﻿using MiScaleExporter.Models;\nusing System;\nusing System.Collections.Generic;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace MiScaleExporter.Services\n{\n    public interface IScale\n    {\n        BodyComposition BodyComposition { get; set; }\n        Task<BodyComposition> GetBodyCompositonAsync(string scaleAddress, User user);\n\n        Task CancelSearchAsync();\n\n        void StopSearch();\n    }\n}\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Services/LogService.cs",
    "content": "﻿using NLog.Config;\nusing NLog.Targets;\nusing NLog;\n\nnamespace MiScaleExporter.Services;\n\npublic class LogService : ILogService\n{\n    private static string TARGET_NAME = \"logmemory\";\n    private static string ERRORS_TARGET_NAME = \"logmemory_errors\";\n    private static bool _isCreated = false;\n    private static LoggingConfiguration _configuration;\n\n    public LogService()\n    {\n    }\n\n    public void LogDebug(string message)\n    {\n    }\n\n    public void LogError(string message)\n    {\n        Application.Current.MainPage.DisplayAlert(\"Error\", message,\n                  \"OK\");\n    }\n\n    public void LogFatal(string message)\n    {\n\n        Application.Current.MainPage.DisplayAlert(\"Fatal\", message,\n                \"OK\");\n    }\n\n    public void LogInfo(string message)\n    {\n        Application.Current.MainPage.DisplayAlert(\"Info\", message,\n                \"OK\");\n    }\n\n    public void LogWarning(string message)\n    {\n\n        Application.Current.MainPage.DisplayAlert(\"Warning\", message,\n                \"OK\");\n    }\n\n    public static LoggingConfiguration CreateLogger()\n    {\n        if (!_isCreated)\n        {\n            _isCreated = true;\n\n            LoggingConfiguration configuration = new LoggingConfiguration();\n\n            MemoryTarget target = new MemoryTarget(TARGET_NAME);\n            target.Layout = \"${message}\";\n\n            configuration.AddTarget(target);\n            LoggingRule traceRule = new LoggingRule(\"*\", NLog.LogLevel.Trace, target);\n            configuration.LoggingRules.Add(traceRule);\n\n            MemoryTarget errorsTarget = new MemoryTarget(ERRORS_TARGET_NAME);\n            errorsTarget.Layout = \"${message}\";\n\n            configuration.AddTarget(errorsTarget);\n            LoggingRule errorsRule = new LoggingRule(\"*\", NLog.LogLevel.Error, errorsTarget);\n            configuration.LoggingRules.Add(errorsRule);\n            LogManager.Configuration = configuration;\n            _configuration = configuration;\n        }\n\n        return _configuration;\n    }\n\n    public static IList<string> GetLogs()\n    {\n        if (!_isCreated)\n        {\n            return new List<string>();\n        }\n\n        var target = LogManager.Configuration.FindTargetByName<MemoryTarget>(TARGET_NAME);\n        var logEvents = target.Logs;\n        return logEvents;\n    }\n\n    public static IList<string> GetErrorLogs()\n    {\n        if (!_isCreated)\n        {\n            return new List<string>();\n        }\n\n        var target = LogManager.Configuration.FindTargetByName<MemoryTarget>(ERRORS_TARGET_NAME);\n        var logEvents = target.Logs;\n        return logEvents;\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Services/Scale.cs",
    "content": "﻿using MiScaleExporter.Models;\nusing Plugin.BLE;\nusing Plugin.BLE.Abstractions.Contracts;\nusing Plugin.BLE.Abstractions.EventArgs;\nusing System.Reflection;\n\nnamespace MiScaleExporter.Services\n{\n    public class Scale : IScale\n    {\n        private ILogService _logService;\n        private IDataInterpreter _dataInterpreter;\n\n        private IAdapter _adapter;\n        private TaskCompletionSource<BodyComposition> _completionSource;\n\n        private BodyComposition _lastSuccessfulBodyComposition;\n        private byte[] _scannedData;\n        private string _scaleBlutetoothAddress;\n        private DateTime? _lastSuccessfulMeasure;\n        private bool _impedanceWaitFinished = false;\n        private bool _impedanceWaitStarted = false;\n        private int _minWeight = 10; // in kilograms\n        private const double KgToLbsConversion = 2.20462;\n\n        private User _user;\n\n        private BodyComposition _receivedBodyComposition;\n\n        public BodyComposition BodyComposition\n        {\n            get { return _receivedBodyComposition; }\n            set { _receivedBodyComposition = value; }\n        }\n\n        public Scale(ILogService logService, IDataInterpreter dataInterpreter)\n        {\n            _logService = logService;\n\n            _adapter = CrossBluetoothLE.Current.Adapter;\n            _adapter.ScanTimeout = 50000;\n            _adapter.ScanTimeoutElapsed += TimeOuted;\n            _dataInterpreter = dataInterpreter;\n        }\n\n        public async Task<BodyComposition> GetBodyCompositonAsync(string scaleAddress, User user)\n        {\n            this.BodyComposition = null;\n            _lastSuccessfulBodyComposition = null;\n            _receivedBodyComposition = null;\n            _impedanceWaitFinished = false;\n            _impedanceWaitStarted = false;\n\n            _user = user;\n            _scaleBlutetoothAddress = scaleAddress;\n            _completionSource = new TaskCompletionSource<BodyComposition>();\n            _adapter.DeviceAdvertised += DeviceAdvertided;\n\n            await _adapter.StartScanningForDevicesAsync();\n            return await _completionSource.Task;\n        }\n\n        private void DeviceAdvertided(object s, DeviceEventArgs a)\n        {\n            var obj = a.Device.NativeDevice;\n            PropertyInfo propInfo = obj.GetType().GetProperty(\"Address\");\n            string address = (string)propInfo.GetValue(obj, null);\n\n            if (address.ToLowerInvariant() == _scaleBlutetoothAddress?.ToLowerInvariant())\n            {\n\n                try\n                {\n                    var device = a.Device;\n                    var bodyCompositionCandidate = GetScanData(device);\n                    if (bodyCompositionCandidate is not null && bodyCompositionCandidate.Weight > _minWeight)\n                    {\n                        this.BodyComposition = bodyCompositionCandidate;\n                    }\n\n                    this.ProcessReceivedData();\n                    this.SetPreviews(bodyCompositionCandidate);\n                }\n                catch (Exception ex)\n                {\n                    _logService.LogError(ex.Message);\n\n                    if (_scannedData != null)\n                    {\n                        _logService.LogInfo(string.Join(\"; \", _scannedData));\n                    }\n                }\n                finally\n                {\n\n                    if (this.BodyComposition != null && (this.BodyComposition.HasImpedance || _impedanceWaitFinished))\n                    {\n                        StopAsync().Wait();\n                        _lastSuccessfulMeasure = this.BodyComposition.Date;\n                        this.BodyComposition.IsValid = true;\n                        _completionSource.SetResult(this.BodyComposition);\n                    }\n                }\n            }\n        }\n\n        private void ProcessReceivedData()\n        {\n            if (this.BodyComposition == null)\n            {\n                return;\n            }\n\n            _lastSuccessfulBodyComposition = this.BodyComposition;\n\n            if (!this.BodyComposition.IsStabilized)\n            {\n                this.BodyComposition = null;\n                return;\n            }\n            else\n            {\n\n                if (_lastSuccessfulMeasure != null && _lastSuccessfulMeasure >= this.BodyComposition.Date)\n                {\n                    this.BodyComposition = null;\n\n                    return;\n                }\n                if (!_impedanceWaitStarted)\n                {\n                    _impedanceWaitStarted = true;\n                    Task.Factory.StartNew(async () =>\n                    {\n                        var seconds = 5;\n                        await Task.Delay(TimeSpan.FromSeconds(seconds));\n                        _impedanceWaitStarted = false;\n                        _impedanceWaitFinished = true;\n\n                    });\n                }\n            }\n        }\n\n        public static string BytesToHex(byte[] bytes)\n        {\n            return BitConverter.ToString(bytes).Replace(\"-\", \"\").ToLower();\n        }\n\n        private void SetPreviews(BodyComposition bodyCompositionCandidate)\n        {\n            if (Preferences.Get(PreferencesKeys.ShowDebugInfo, false))\n            {\n                ScaleMeasurement.Instance.FoundScale = bodyCompositionCandidate != null ? \"Connected to scale: Yes\" : \"Connected to scale: No\";\n                if (bodyCompositionCandidate != null)\n                {\n                    ScaleMeasurement.Instance.DebugData = (bodyCompositionCandidate.IsStabilized ? \"Stabilized: Yes\" : \"Stabilized: No\") + \" \" + (bodyCompositionCandidate.HasImpedance ? \"Impedance: Yes\" : \"Impedance: No\");\n                    if (bodyCompositionCandidate.RawDataLog != null && bodyCompositionCandidate.RawDataLog.Count > 0)\n                    {\n                        ScaleMeasurement.Instance.RawData = string.Join(\"|\", bodyCompositionCandidate.RawDataLog.Select(BytesToHex));\n                    }\n                    else if (bodyCompositionCandidate.ReceivedRawData != null && bodyCompositionCandidate.ReceivedRawData.Length > 0)\n                    {\n                        ScaleMeasurement.Instance.RawData = BytesToHex(bodyCompositionCandidate.ReceivedRawData);\n                    }\n                }\n            }\n            if (this.BodyComposition != null)\n            {\n                ScaleMeasurement.Instance.Weight = GetWeightScanningLabel(this.BodyComposition.Weight, Preferences.Get(PreferencesKeys.DisplayWeightInLbs, false));\n            }\n\n        }\n\n        private string GetWeightScanningLabel(double valueInKg, bool convertToLbs)\n        {\n            return $\"{(convertToLbs ? valueInKg * KgToLbsConversion : valueInKg).ToString(\"0.##\")}{(convertToLbs ? \"lbs\" : \"kg\")}\";\n        }\n\n        private BodyComposition GetScanData(IDevice device)\n        {\n            if (device != null)\n            {\n                var data = device.AdvertisementRecords\n                    .Where(x => x.Type == Plugin.BLE.Abstractions.AdvertisementRecordType.ServiceData) //0x16\n                    .Select(x => x.Data)\n                    .FirstOrDefault();\n                _scannedData = data;\n\n                var bc = this._dataInterpreter.ComputeData(data, _user, _scaleBlutetoothAddress);\n                if (bc is not null)\n                {\n                    bc.ReceivedRawData = _scannedData;\n                    if (!bc.RawDataLog.Contains(_scannedData))\n                    {\n                        bc.RawDataLog.Add(_scannedData);\n                    }\n                }\n\n                return bc;\n            }\n\n            return null;\n        }\n\n        private void CalculateBMIIfEmpty()\n        {\n            if (this.BodyComposition is not null && this.BodyComposition.BMI == 0 && _user.Height != 0)\n            {\n                var heightInMeters = (double)_user.Height / 100;\n                this.BodyComposition.BMI = Math.Round(this.BodyComposition.Weight / (heightInMeters * heightInMeters), 2);\n            }\n        }\n\n        public async Task CancelSearchAsync()\n        {\n            try\n            {\n                if (this.BodyComposition != null)\n                {\n                    this.BodyComposition.IsValid = false;\n                }\n                if (!_completionSource.Task.IsCompleted)\n                {\n                    _completionSource.SetResult(this.BodyComposition);\n                }\n\n            }\n            catch (Exception ex)\n            {\n                _logService.LogError(ex.Message);\n            }\n\n            await StopAsync();\n        }\n\n        public void StopSearch()\n        {\n            StopAsync().Wait();\n\n            if (this.BodyComposition is not null)\n            {\n                this.BodyComposition.IsValid = true;\n            }\n            else if (_lastSuccessfulBodyComposition is not null)\n            {\n                this.BodyComposition = _lastSuccessfulBodyComposition;\n                this.BodyComposition.IsValid = true;\n            }\n            CalculateBMIIfEmpty();\n        }\n\n        private void TimeOuted(object s, EventArgs e)\n        {\n            StopAsync().Wait();\n            _completionSource.SetResult(this.BodyComposition);\n        }\n\n        private async Task StopAsync()\n        {\n            await _adapter.StopScanningForDevicesAsync();\n\n            _adapter.DeviceAdvertised -= DeviceAdvertided;\n        }\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Utils/DoubleValueParser.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace MiScaleExporter.MAUI.Utils\n{\n    public static class DoubleValueParser\n    {\n        public static bool IsValid(string value)\n        {\n            if (string.IsNullOrEmpty(value))\n            {\n                return true;\n            }\n\n            var parsed = ParseValueFromUsersCulture(value);\n\n            return parsed != null;\n\n        }\n\n        public static string CheckValue(string value)\n        {\n            if (IsValid(value))\n            {\n                return value;\n            }\n            if (value.Length > 1)\n            {\n                return CheckValue(value.Remove(value.Length - 1));\n            }\n            return string.Empty;\n\n        }\n\n        public static double? ParseValueFromUsersCulture(string value)\n        {\n            if (string.IsNullOrEmpty(value))\n            {\n                return null;\n            }\n            var parsed = ParseDouble(value);\n            if (parsed == null)\n            {\n                parsed = ParseDouble(value.Replace(',', '.'));\n            }\n            if (parsed == null)\n            {\n                parsed = ParseDouble(value.Replace('.', ','));\n            }\n            if (parsed == null) // when , or . is last character\n            {\n                parsed = ParseDouble(value.Remove(value.Length - 1));\n            }\n\n            return parsed;\n        }\n\n        private static double? ParseDouble(string value)\n        {\n            if (double.TryParse(value, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out double parsed))\n            {\n                return parsed;\n            }\n            else\n            {\n                return null;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/ViewModels/AboutViewModel.cs",
    "content": "﻿using MiScaleExporter.MAUI.Resources.Localization;\nusing System.Windows.Input;\n \n \n\nnamespace MiScaleExporter.MAUI.ViewModels;\n\npublic class AboutViewModel : BaseViewModel\n{\n    public AboutViewModel()\n    {\n        this.Title = AppSnippets.MiScaleExporter;\n        GoToScanCommand = new Command(async () =>\n            await Shell.Current.GoToAsync(\"///ScalePage\"));\n        OpenGithubCommand = new Command(async () =>\n            await Browser.OpenAsync(\"https://github.com/lswiderski/mi-scale-exporter\"));\n        OpenCoffeeCommand = new Command(async () =>\n            await Browser.OpenAsync(\"https://www.buymeacoffee.com/lukaszswiderski\"));\n        OpenHelpCommand = new Command(async () =>\n         await Shell.Current.GoToAsync(\"///HelpPage\"));\n    }\n    \n    public ICommand GoToScanCommand { get; }\n    public ICommand OpenGithubCommand { get; }\n    public ICommand OpenCoffeeCommand { get; }\n    public ICommand OpenHelpCommand { get; }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/ViewModels/BaseViewModel.cs",
    "content": "﻿using MiScaleExporter.Models;\nusing MiScaleExporter.Services;\nusing System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Runtime.CompilerServices;\n \n\nnamespace MiScaleExporter.MAUI.ViewModels\n{\n    public class BaseViewModel : INotifyPropertyChanged\n    {\n        bool isBusy = false;\n        public bool IsBusy\n        {\n            get { return isBusy; }\n            set { SetProperty(ref isBusy, value); }\n        }\n\n        string title = string.Empty;\n        public string Title\n        {\n            get { return title; }\n            set { SetProperty(ref title, value); }\n        }\n\n        protected bool SetProperty<T>(ref T backingStore, T value,\n            [CallerMemberName] string propertyName = \"\",\n            Action onChanged = null)\n        {\n            if (EqualityComparer<T>.Default.Equals(backingStore, value))\n                return false;\n\n            backingStore = value;\n            onChanged?.Invoke();\n            OnPropertyChanged(propertyName);\n            return true;\n        }\n\n        #region INotifyPropertyChanged\n        public event PropertyChangedEventHandler PropertyChanged;\n        protected void OnPropertyChanged([CallerMemberName] string propertyName = \"\")\n        {\n            var changed = PropertyChanged;\n            if (changed == null)\n                return;\n\n            changed.Invoke(this, new PropertyChangedEventArgs(propertyName));\n        }\n        #endregion\n\n        protected void NotifyAllPropertiesChanged()\n        {\n            PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(null));\n        }\n    }\n}\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/ViewModels/FormViewModel.cs",
    "content": "﻿using CommunityToolkit.Maui.Alerts;\nusing CommunityToolkit.Maui.Storage;\nusing MiScaleExporter.MAUI;\nusing MiScaleExporter.MAUI.Resources.Localization;\nusing MiScaleExporter.MAUI.Utils;\nusing MiScaleExporter.Models;\nusing MiScaleExporter.Services;\nusing System.Globalization;\nusing System.Threading;\nusing YetAnotherGarminConnectClient.Dto.Garmin.Fit;\n\nnamespace MiScaleExporter.MAUI.ViewModels\n{\n    public class FormViewModel : BaseViewModel, IFormViewModel\n    {\n        private readonly IGarminService _garminService;\n        private readonly IFileSaver _fileSaver;\n        private const double KgToLbsConversion = 2.20462;\n\n        public FormViewModel(IGarminService garminService, IFileSaver fileSaver)\n        {\n            _garminService = garminService;\n            Title = AppSnippets.GarminBodyCompositionForm;\n            Date = DateTime.Now;\n            Time = DateTime.Now.TimeOfDay;\n            _muscleMassAsKg = true;\n            _showWeightInKg = true;\n            UploadCommand = new Command(OnUpload, ValidateSave);\n            GenerateFitFileCommand = new Command(OnGenerateFitFileAsync);\n            CancelMFACommand = new Command(OnCancelMFA);\n            this.PropertyChanged +=\n                (_, __) => UploadCommand.ChangeCanExecute();\n\n            this._fileSaver = fileSaver;\n        }\n\n        public async Task LoadPreferencesAsync()\n        {\n            this._email = Preferences.Get(PreferencesKeys.GarminUserEmail, string.Empty);\n            this._password = await SecureStorage.GetAsync(PreferencesKeys.GarminUserPassword);\n\n            this._accessToken = await SecureStorage.GetAsync(PreferencesKeys.GarminUserAccessToken);\n            this._tokenSecret = await SecureStorage.GetAsync(PreferencesKeys.GarminUserTokenSecret);\n            this._saveTokens = !string.IsNullOrWhiteSpace(_email) && !string.IsNullOrWhiteSpace(_password);\n\n            this.ShowEmail = string.IsNullOrWhiteSpace(_email);\n            this.ShowPassword = string.IsNullOrWhiteSpace(_password);\n\n            this._displayWeightInLbs = Preferences.Get(PreferencesKeys.DisplayWeightInLbs, false);\n            this.ShowWeightInKg = !_displayWeightInLbs;\n            this.ShowWeightInLbs = _displayWeightInLbs;\n\n            this.MuscleMassAsPercentage = Preferences.Get(PreferencesKeys.MuscleMassAsPercentage, false);\n            this.MuscleMassAsKg = (!MuscleMassAsPercentage && ShowWeightInKg);\n            this.MuscleMassAsLbs = (!MuscleMassAsPercentage && !ShowWeightInKg);\n\n\n            this.Date = DateTime.Now;\n            this.Time = DateTime.Now.TimeOfDay;\n        }\n        private bool ValidateSave()\n        {\n            return !String.IsNullOrWhiteSpace(_email)\n                   && !String.IsNullOrWhiteSpace(_password);\n        }\n\n        public void AutoUpload()\n        {\n            if (!string.IsNullOrWhiteSpace(_email)\n                 && !string.IsNullOrWhiteSpace(_password))\n            {\n                OnUpload();\n            }\n        }\n\n        private async void OnUpload()\n        {\n            this.IsBusyForm = true;\n            var credencials = new CredentialsData\n            {\n                Email = _email,\n                Password = _password,\n                AccessToken = this._accessToken,\n                TokenSecret = this._tokenSecret,\n            };\n            var response = await this._garminService.UploadAsync(this.PrepareRequest(), Date.Date.Add(Time), credencials);\n            var message = (response?.IsSuccess ?? false) ? AppSnippets.Uploaded : response?.Message; \n            await Application.Current.MainPage.DisplayAlert(AppSnippets.Response, message, AppSnippets.OK);\n            this.IsBusyForm = false;\n            if (this._saveTokens)\n            {\n                this._accessToken = response?.AccessToken ?? string.Empty;\n                this._tokenSecret = response?.TokenSecret ?? string.Empty;\n            }\n            else\n            {\n                this._accessToken = string.Empty;\n                this._tokenSecret = string.Empty;\n            }\n            await SecureStorage.SetAsync(PreferencesKeys.GarminUserAccessToken, this._accessToken);\n            await SecureStorage.SetAsync(PreferencesKeys.GarminUserTokenSecret, this._tokenSecret);\n            if (response?.MFARequested ?? false)    \n            {\n                this.ShowMFACode = true;\n                this.ShowEmail = false;\n                this.ShowPassword = false;\n                this.ExternalApiClientId = response?.ExternalApiClientId;\n            }\n            else\n            {\n                this.ShowMFACode = false;\n                this.MFACode = null;\n                this.ExternalApiClientId = null;\n                this.ShowEmail = string.IsNullOrWhiteSpace(Preferences.Get(PreferencesKeys.GarminUserEmail, string.Empty));\n                this.ShowPassword = string.IsNullOrWhiteSpace(await SecureStorage.GetAsync(PreferencesKeys.GarminUserPassword));\n            }\n            // This will pop the current page off the navigation stack\n            await Shell.Current.GoToAsync(\"..?autoUpload=false\");\n        }\n\n        private async void OnGenerateFitFileAsync()\n        {\n            this.IsBusyForm = true;\n\n            var response = await this._garminService.GenerateFitFileAsync(this.PrepareRequest(), Date.Date.Add(Time));\n\n            if (!response.IsSuccess && response.file != null)\n            {\n                await Application.Current.MainPage.DisplayAlert(AppSnippets.Response, response?.Message, AppSnippets.OK);\n            }\n            else\n            {\n                using var stream = new MemoryStream(response.file);\n                var fileSaverResult = await _fileSaver.SaveAsync($\"activity_{Date.Date.Add(Time).ToShortDateString()}.fit\", stream);\n                if (fileSaverResult.IsSuccessful)\n                {\n                    await Toast.Make($\"The file was saved successfully to location: {fileSaverResult.FilePath}\").Show();\n                }\n                else\n                {\n                    await Toast.Make($\"The file was not saved successfully with error: {fileSaverResult.Exception.Message}\").Show();\n                }\n            }\n           \n            this.IsBusyForm = false;\n\n            // This will pop the current page off the navigation stack\n            await Shell.Current.GoToAsync(\"..?autoUpload=false\");\n        }\n\n        private async void OnCancelMFA()\n        {\n            this.ShowMFACode = false;\n            this.MFACode = null;\n            this.ExternalApiClientId = null;\n            this.ShowEmail = string.IsNullOrWhiteSpace(Preferences.Get(PreferencesKeys.GarminUserEmail, string.Empty));\n            this.ShowPassword = string.IsNullOrWhiteSpace(await SecureStorage.GetAsync(PreferencesKeys.GarminUserPassword));\n        }\n\n        private BodyComposition PrepareRequest()\n        {\n            var bc = new BodyComposition\n            {\n                Fat = DoubleValueParser.ParseValueFromUsersCulture(_fat) ?? 0,\n                BodyType = _bodyType ?? 0,\n                Weight = ConvertToKg(DoubleValueParser.ParseValueFromUsersCulture(_weight) ?? 0),\n                BoneMass = ConvertToKg(DoubleValueParser.ParseValueFromUsersCulture(_boneMass) ?? 0),\n                MuscleMass = ConvertToKg(DoubleValueParser.ParseValueFromUsersCulture(_muscleMass) ?? 0),\n                MetabolicAge = DoubleValueParser.ParseValueFromUsersCulture(_metabolicAge) ?? 0,\n                ProteinPercentage = DoubleValueParser.ParseValueFromUsersCulture(_proteinPercentage) ?? 0,\n                VisceralFat = DoubleValueParser.ParseValueFromUsersCulture(_visceralFat) ?? 0,\n                BMI = DoubleValueParser.ParseValueFromUsersCulture(_bmi) ?? 0,\n                BMR = DoubleValueParser.ParseValueFromUsersCulture(_bmr) ?? 0,\n                WaterPercentage = DoubleValueParser.ParseValueFromUsersCulture(_waterPercentage) ?? 0,\n                MFACode = _mfaCode,\n                ExternalApiClientId = _externalApiClientId\n            };\n\n            if (Preferences.Get(PreferencesKeys.MuscleMassAsPercentage, false) \n                && bc.MuscleMass != 0 \n                && bc.Weight != 0)\n            {\n                bc.MuscleMass = (bc.MuscleMass / 100) * bc.Weight;\n            }\n            return bc;\n        }\n\n        public void LoadBodyComposition()\n        {\n            if (App.BodyComposition is null) return;\n\n            Weight = ConvertFromKg(App.BodyComposition.Weight).ToString(\"0.##\");\n            BMI = App.BodyComposition.BMI.ToString();\n            BoneMass = ConvertFromKg(App.BodyComposition.BoneMass).ToString(\"0.##\");\n            MuscleMass = ConvertFromKg(App.BodyComposition.MuscleMass).ToString(\"0.##\");\n            IdealWeight = ConvertFromKg(App.BodyComposition.IdealWeight).ToString(\"0.##\");\n            BMR = App.BodyComposition.BMR.ToString();\n            MetabolicAge = App.BodyComposition.MetabolicAge.ToString();\n            ProteinPercentage = App.BodyComposition.ProteinPercentage.ToString();\n            VisceralFat = App.BodyComposition.VisceralFat.ToString();\n            Fat = App.BodyComposition.Fat.ToString();\n            WaterPercentage = App.BodyComposition.WaterPercentage.ToString();\n            BodyType = App.BodyComposition.BodyType;\n            IsAutomaticCalculation = true;\n        }\n\n        public Command UploadCommand { get; }\n        public Command CancelMFACommand { get; }\n\n        public Command GenerateFitFileCommand { get; }\n\n        private string _weight;\n\n        public string Weight\n        {\n            get => _weight;\n            set => SetProperty(ref _weight, DoubleValueParser.CheckValue(value));\n        }\n\n        private string _bmi;\n\n        public string BMI\n        {\n            get => _bmi;\n            set => SetProperty(ref _bmi, DoubleValueParser.CheckValue(value));\n        }\n\n        private string _idealWeight;\n\n        public string IdealWeight\n        {\n            get => _idealWeight;\n            set => SetProperty(ref _idealWeight, DoubleValueParser.CheckValue(value));\n        }\n\n        private string _metabolicAge;\n\n        public string MetabolicAge\n        {\n            get => _metabolicAge;\n            set => SetProperty(ref _metabolicAge, DoubleValueParser.CheckValue(value));\n        }\n\n        private string _proteinPercentage;\n\n        public string ProteinPercentage\n        {\n            get => _proteinPercentage;\n            set => SetProperty(ref _proteinPercentage, DoubleValueParser.CheckValue(value));\n        }\n\n        private string _bmr;\n\n        public string BMR\n        {\n            get => _bmr;\n            set => SetProperty(ref _bmr, DoubleValueParser.CheckValue(value));\n        }\n\n        private string _fat;\n\n        public string Fat\n        {\n            get => _fat;\n            set => SetProperty(ref _fat, DoubleValueParser.CheckValue(value));\n        }\n\n        private string _muscleMass;\n\n        public string MuscleMass\n        {\n            get => _muscleMass;\n            set => SetProperty(ref _muscleMass, DoubleValueParser.CheckValue(value));\n        }\n\n        private string _boneMass;\n\n        public string BoneMass\n        {\n            get => _boneMass;\n            set => SetProperty(ref _boneMass, DoubleValueParser.CheckValue(value));\n        }\n\n        private string _visceralFat;\n\n        public string VisceralFat\n        {\n            get => _visceralFat;\n            set => SetProperty(ref _visceralFat, DoubleValueParser.CheckValue(value));\n        }\n\n        private int? _bodyType;\n\n        public int? BodyType\n        {\n            get => _bodyType;\n            set => SetProperty(ref _bodyType, value);\n        }\n\n        private string _waterPercentage;\n\n        public string WaterPercentage\n        {\n            get => _waterPercentage;\n            set => SetProperty(ref _waterPercentage, DoubleValueParser.CheckValue(value));\n        }\n\n        private string _email;\n\n        private string _password;\n\n        private string _accessToken;\n\n        private string _tokenSecret;\n        private bool _saveTokens;\n\n        private DateTime _date;\n\n        public DateTime Date\n        {\n            get => _date;\n            set => SetProperty(ref _date, value);\n        }\n\n        private TimeSpan _time;\n\n        public TimeSpan Time\n        {\n            get => _time;\n            set => SetProperty(ref _time, value);\n        }\n\n        private bool _isAutomaticCalculation;\n\n        public bool IsAutomaticCalculation\n        {\n            get => _isAutomaticCalculation;\n            set => SetProperty(ref _isAutomaticCalculation, value);\n        }\n\n        private bool _isBusyForm;\n\n        public bool IsBusyForm\n        {\n            get => _isBusyForm;\n            set => SetProperty(ref _isBusyForm, value);\n        }\n\n        private bool _showMFACode;\n        public bool ShowMFACode\n        {\n            get => _showMFACode;\n            set => SetProperty(ref _showMFACode, value);\n        }\n\n        private string _externalApiClientId;\n        public string ExternalApiClientId\n        {\n            get => _externalApiClientId;\n            set\n            {\n                SetProperty(ref _externalApiClientId, value);\n            }\n        }\n        private string _mfaCode;\n        public string MFACode\n        {\n            get => _mfaCode;\n            set\n            {\n                SetProperty(ref _mfaCode, value);\n            }\n        }\n\n        private bool _muscleMassAsPercentage;\n        public bool MuscleMassAsPercentage\n        {\n            get => _muscleMassAsPercentage;\n            set => SetProperty(ref _muscleMassAsPercentage, value);\n        }\n\n        private bool _muscleMassAsKg;\n        public bool MuscleMassAsKg\n        {\n            get => _muscleMassAsKg;\n            set => SetProperty(ref _muscleMassAsKg, value);\n        }\n\n        private bool _muscleMassAsLbs;\n        public bool MuscleMassAsLbs\n        {\n            get => _muscleMassAsLbs;\n            set => SetProperty(ref _muscleMassAsLbs, value);\n        }\n\n        private bool _showWeightInKg;\n        public bool ShowWeightInKg\n        {\n            get => _showWeightInKg;\n            set => SetProperty(ref _showWeightInKg, value);\n        }\n        private bool _showWeightInLbs;\n        public bool ShowWeightInLbs\n        {\n            get => _showWeightInLbs;\n            set => SetProperty(ref _showWeightInLbs, value);\n        }\n\n        private double ConvertFromKg(double valueInKg)\n        {\n            return _displayWeightInLbs ? valueInKg * KgToLbsConversion : valueInKg;\n        }\n\n        private double ConvertToKg(double displayValue)\n        {\n            return _displayWeightInLbs ? displayValue / KgToLbsConversion : displayValue;\n        }\n\n        private bool _displayWeightInLbs;\n\n        public string Email\n        {\n            get => _email;\n            set\n            {\n                SetProperty(ref _email, value);\n                UploadCommand?.ChangeCanExecute();\n            }\n        }\n\n        public string Password\n        {\n            get => _password;\n            set\n            {\n                SetProperty(ref _password, value);\n                UploadCommand?.ChangeCanExecute();\n            }\n        }\n\n        private bool _showEmail;\n        private bool _showPassword;\n\n        public bool ShowEmail\n        {\n            get => _showEmail;\n            set => SetProperty(ref _showEmail, value);\n        }\n\n        public bool ShowPassword\n        {\n            get => _showPassword;\n            set => SetProperty(ref _showPassword, value);\n        }\n\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/ViewModels/IFormViewModel.cs",
    "content": "﻿namespace MiScaleExporter.MAUI.ViewModels\n{\n    public interface IFormViewModel\n    {\n        void LoadBodyComposition();\n        Task LoadPreferencesAsync();\n\n        void AutoUpload();\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/ViewModels/IScaleViewModel.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Text;\n \n\nnamespace MiScaleExporter.MAUI.ViewModels\n{\n    public interface IScaleViewModel\n    {\n        Task CheckPreferencesAsync();\n        Task LoadPreferencesAsync();\n    }\n}\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/ViewModels/ISettingsViewModel.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace MiScaleExporter.MAUI.ViewModels\n{\n    public interface ISettingsViewModel\n    {\n        void SexRadioSetToMale();\n        void SexRadioSetToFemale();\n        void ScaleTypeSetToBodyCompositionScale();\n        void ScaleTypeSetToMiscale();\n        void ScaleTypeSetToS400();\n        Task LoadPreferencesAsync();\n    }\n}\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/ViewModels/ScaleViewModel.cs",
    "content": "﻿using MiScaleExporter.Models;\nusing MiScaleExporter.Services;\nusing MiScaleExporter.Permission;\nusing MiScaleExporter.MAUI.Resources.Localization;\nusing Plugin.BLE;\nusing Plugin.BLE.Abstractions;\n\nnamespace MiScaleExporter.MAUI.ViewModels\n{\n    public class ScaleViewModel : BaseViewModel, IScaleViewModel\n    {\n        private readonly IScale _scale;\n        private readonly ILogService _logService;\n\n        private string _address;\n        private int _age;\n        private int _height;\n        private Models.Sex _sex;\n        private ScaleType _scaleType;\n\n        private string _bindkey;\n\n        public ScaleViewModel(IScale scale, ILogService logService)\n        {\n            _scale = scale;\n            _logService = logService;\n\n            Title = AppSnippets.MiScaleData;\n            CancelCommand = new Command(OnCancel);\n            StopCommand = new Command(OnStop);\n        }\n\n        public async Task CheckPreferencesAsync()\n        {\n            ScaleMeasurement.Instance.Weight = \"\";\n            App.BodyComposition = null;\n            var hasPermissions = await CheckPermissions();\n\n            if(hasPermissions)\n            {\n                await this.LoadPreferencesAsync();\n                if (!string.IsNullOrWhiteSpace(_address))\n                {\n                    OnScan();\n                }\n                else\n                {\n                   // await App.Current.MainPage.Navigation.PopAsync();\n                    await Shell.Current.GoToAsync($\"//Settings\");\n                }\n            }\n           \n        }\n\n        public async Task LoadPreferencesAsync()\n        {\n            this._age = Preferences.Get(PreferencesKeys.UserAge, 25);\n            this._height = Preferences.Get(PreferencesKeys.UserHeight, 170);\n            this._sex = (Models.Sex)Preferences.Get(PreferencesKeys.UserSex, (byte)Models.Sex.Male);\n            this._address = Preferences.Get(PreferencesKeys.MiScaleBluetoothAddress, string.Empty);\n            this._scaleType = (ScaleType)Preferences.Get(PreferencesKeys.ScaleType, (byte)ScaleType.MiBodyCompositionScale);\n            this._bindkey = Preferences.Get(PreferencesKeys.S400Bindkey, string.Empty);\n        }\n\n        private async void OnScan()\n        {\n            await StartScan();\n        }\n\n        private async Task<bool> CheckPermissions()\n        {\n            if (DeviceInfo.Platform == DevicePlatform.Android)\n            {\n                if (DeviceInfo.Version.Major >= 12)\n                {\n                    if (await GetBluetoothPermissionStatusAsync() != PermissionStatus.Granted)\n                    {\n                        await Application.Current.MainPage.DisplayAlert(AppSnippets.Problem, AppSnippets.PermissionBluetoothRequired,\n                           AppSnippets.OK);\n                        return false;\n                    }\n\n                    if (await GetLocationWhenInUsePermissionStatusAsync() != PermissionStatus.Granted)\n                    {\n                        await Application.Current.MainPage.DisplayAlert(AppSnippets.Problem, AppSnippets.PermissionLocationRequired,\n                             AppSnippets.OK);\n                        return false;\n                    }\n                }\n                else\n                {\n                    if (await GetLocationWhenInUsePermissionStatusAsync() != PermissionStatus.Granted)\n                    {\n                        if(await GetLocationAlwaysPermissionStatusAsync() != PermissionStatus.Granted)\n                        {\n                            await Application.Current.MainPage.DisplayAlert(AppSnippets.Problem, AppSnippets.PermissionLocationRequired,\n                            AppSnippets.OK);\n                            return false;\n                        }\n                    }\n                }\n\n            }\n\n            // Check if Bluetooth is enabled\n            if (CrossBluetoothLE.Current.State != BluetoothState.On)\n            {\n                await Application.Current.MainPage.DisplayAlert(\n                    AppSnippets.Problem,\n                    AppSnippets.BluetoothDisabled,\n                    AppSnippets.OK);\n                return false;\n            }\n\n            return true;\n\n        }\n\n        private async Task StartScan()\n        {\n            ScanningLabel = string.Empty;\n            ScaleMeasurement.Instance.Weight = \"0\";\n            this.IsBusyForm = true;\n            await this._scale.GetBodyCompositonAsync(_address,\n                new User { Sex = _sex, Age = _age, Height = _height, ScaleType = _scaleType, BindKey = _bindkey });\n            this.OnStop();\n        }\n\n        private async void OnStop()\n        {\n            this._scale.StopSearch();\n            this.IsBusyForm = false;\n            if (this._scale.BodyComposition is null || !this._scale.BodyComposition.IsValid)\n            {\n                var msg = AppSnippets.DataCouldNotBeObtained;\n                await Application.Current.MainPage.DisplayAlert(AppSnippets.Problem, msg,\n                    AppSnippets.OK);\n                _logService.LogError(msg);\n                ScanningLabel = AppSnippets.NotFound;\n            }\n            else\n            {\n                App.BodyComposition = this._scale.BodyComposition;\n                await Shell.Current.GoToAsync($\"//FormPage?autoUpload={Preferences.Get(PreferencesKeys.OneClickScanAndUpload, false)}\");\n            }\n        }\n\n        private async void OnCancel()\n        {\n            await this._scale.CancelSearchAsync();\n            this.IsBusyForm = false;\n        }\n\n        private async Task<PermissionStatus> GetLocationWhenInUsePermissionStatusAsync()\n        {\n            var locationPermissionStatus = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();\n            if (locationPermissionStatus != PermissionStatus.Granted)\n            {\n                locationPermissionStatus = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();\n            }\n\n            return locationPermissionStatus;\n        }\n\n        private async Task<PermissionStatus> GetLocationAlwaysPermissionStatusAsync()\n        {\n            var locationPermissionStatus = await Permissions.CheckStatusAsync<Permissions.LocationAlways>();\n            if (locationPermissionStatus != PermissionStatus.Granted)\n            {\n                locationPermissionStatus = await Permissions.RequestAsync<Permissions.LocationAlways>();\n            }\n\n            return locationPermissionStatus;\n        }\n\n        private async Task<PermissionStatus> GetBluetoothPermissionStatusAsync()\n        {\n            var bluetoothPermission = DependencyService.Get<IBluetoothConnectPermission>();\n            var status = await bluetoothPermission.CheckStatusAsync();\n            if (status != PermissionStatus.Granted)\n            {\n                status = await bluetoothPermission.RequestAsync();\n            }\n            return status;\n        }\n\n        public Command CancelCommand { get; }\n        public Command StopCommand { get; }\n\n        private string _scanningLabel;\n\n        public string ScanningLabel\n        {\n            get => _scanningLabel;\n            set => SetProperty(ref _scanningLabel, value);\n        }\n\n        private bool _isBusyForm;\n\n        public bool IsBusyForm\n        {\n            get => _isBusyForm;\n            set => SetProperty(ref _isBusyForm, value);\n        }\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/ViewModels/SettingsViewModel.cs",
    "content": "﻿using System;\nusing System.Windows.Input;\nusing MiScaleExporter.MAUI.Resources.Localization;\nusing MiScaleExporter.Models;\n\n\n\nnamespace MiScaleExporter.MAUI.ViewModels\n{\n    public class SettingsViewModel : BaseViewModel, ISettingsViewModel\n    {\n        public SettingsViewModel()\n        {\n            this.Title = AppSnippets.Settings;\n            // Initialize birthDate with a reasonable default to avoid binding issues\n            this._birthDate = DateTime.Today.AddYears(-25);\n            ResetCommand = new Command(() =>\n                {\n                    Preferences.Remove(PreferencesKeys.ApiServerAddressOverride);\n                    this.ApiAddress = string.Empty;\n                    Preferences.Remove(PreferencesKeys.OneClickScanAndUpload);\n                    Preferences.Remove(PreferencesKeys.UseExternalAPI);\n                    Preferences.Remove(PreferencesKeys.ShowDebugInfo);\n                    Preferences.Remove(PreferencesKeys.HideAds);\n                    Preferences.Remove(PreferencesKeys.MuscleMassAsPercentage);\n                    Preferences.Remove(PreferencesKeys.DisplayWeightInLbs);\n                    Preferences.Remove(PreferencesKeys.UseChinaServer);\n                    Preferences.Remove(PreferencesKeys.UserAge);\n                    Preferences.Remove(PreferencesKeys.UserBirthDate);\n                    Preferences.Remove(PreferencesKeys.UseBirthDateMode);\n                    this.UseBirthDateMode = false;\n                    this.ManualAge = \"25\";\n                }\n            );\n            GetBLEKeyCommand = new Command(async () => await Launcher.OpenAsync(\"https://lswiderski.github.io/mi-scale-exporter/#steps-to-connect-xiaomi-body-composition-scale-s400\"));\n            ResetTokensCommand = new Command(_clearTokens);\n        }\n\n        public ICommand ResetCommand { get; }\n        public ICommand GetBLEKeyCommand { get; }\n        public ICommand ResetTokensCommand { get; }\n\n\n        public async Task LoadPreferencesAsync()\n        {\n            _isLoadingPreferences = true;\n            try\n            {\n                this._apiAddress = Preferences.Get(PreferencesKeys.ApiServerAddressOverride, string.Empty);\n                this._oneClickScanAndUpload = Preferences.Get(PreferencesKeys.OneClickScanAndUpload, false);\n                this._useExternalAPI = Preferences.Get(PreferencesKeys.UseExternalAPI, false);\n                this._showDebugInfo = Preferences.Get(PreferencesKeys.ShowDebugInfo, false);\n                this._hideAds = Preferences.Get(PreferencesKeys.HideAds, false);\n                this._muscleMassAsPercentage = Preferences.Get(PreferencesKeys.MuscleMassAsPercentage, false);\n                this._displayWeightInLbs = Preferences.Get(PreferencesKeys.DisplayWeightInLbs, false);\n                this._useChinaServer = Preferences.Get(PreferencesKeys.UseChinaServer, false);\n\n                // Load age or birthday mode\n                this._useBirthDateMode = Preferences.Get(PreferencesKeys.UseBirthDateMode, false);\n                \n                if (_useBirthDateMode)\n                {\n                    // Load birthday\n                    var birthDateTicks = Preferences.Get(PreferencesKeys.UserBirthDate, 0L);\n                    this._birthDate = birthDateTicks > 0 ? new DateTime(birthDateTicks) : DateTime.Today.AddYears(-25);\n                    this._manualAge = 0; // Not used in birthday mode\n                }\n                else\n                {\n                    // Load manual age\n                    this._manualAge = Preferences.Get(PreferencesKeys.UserAge, 25);\n                    this._birthDate = DateTime.Today.AddYears(-_manualAge); // For reference only\n                }\n                \n                this._height = Preferences.Get(PreferencesKeys.UserHeight, 170);\n                this._sex = (Sex)Preferences.Get(PreferencesKeys.UserSex, (byte)Sex.Male);\n                this._address = Preferences.Get(PreferencesKeys.MiScaleBluetoothAddress, string.Empty);\n                this._scaleType = (ScaleType)Preferences.Get(PreferencesKeys.ScaleType, (byte)ScaleType.MiBodyCompositionScale);\n                this._email = Preferences.Get(PreferencesKeys.GarminUserEmail, string.Empty);\n                this._password = await SecureStorage.GetAsync(PreferencesKeys.GarminUserPassword);\n                this._bindkey = Preferences.Get(PreferencesKeys.S400Bindkey, string.Empty);\n                NotifyAllPropertiesChanged();\n            }\n            finally\n            {\n                _isLoadingPreferences = false;\n            }\n        }\n\n        private bool ValidateProfile()\n        {\n            return !String.IsNullOrWhiteSpace(_address)\n                                        && _height > 0 && _height < 220\n                                        && Age > 0 && Age < 99;\n        }\n\n        private string _apiAddress;\n\n        public string ApiAddress\n        {\n            get => _apiAddress;\n            set\n            {\n                if (string.IsNullOrEmpty(value))\n                {\n                    Preferences.Remove(PreferencesKeys.ApiServerAddressOverride);\n                }\n                else if (Uri.TryCreate(value, UriKind.Absolute, out var uri))\n                {\n                    if (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps)\n                    {\n                        Preferences.Set(PreferencesKeys.ApiServerAddressOverride, value);\n                    }\n                }\n                SetProperty(ref _apiAddress, value);\n            }\n        }\n\n\n\n        private bool _oneClickScanAndUpload;\n\n        public bool OneClickScanAndUpload\n        {\n            get => _oneClickScanAndUpload;\n            set\n            {\n                Preferences.Set(PreferencesKeys.OneClickScanAndUpload, value);\n                SetProperty(ref _oneClickScanAndUpload, value);\n            }\n        }\n\n        private bool _useExternalAPI;\n\n        public bool UseExternalAPI\n        {\n            get => _useExternalAPI;\n            set\n            {\n                Preferences.Set(PreferencesKeys.UseExternalAPI, value);\n                SetProperty(ref _useExternalAPI, value);\n            }\n        }\n\n        private bool _muscleMassAsPercentage;\n\n        public bool MuscleMassAsPercentage\n        {\n            get => _muscleMassAsPercentage;\n            set\n            {\n                Preferences.Set(PreferencesKeys.MuscleMassAsPercentage, value);\n                SetProperty(ref _muscleMassAsPercentage, value);\n            }\n        }\n\n        private bool _displayWeightInLbs;\n\n        public bool DisplayWeightInLbs\n        {\n            get => _displayWeightInLbs;\n            set\n            {\n                Preferences.Set(PreferencesKeys.DisplayWeightInLbs, value);\n                SetProperty(ref _displayWeightInLbs, value);\n            }\n        }\n\n        private bool _useChinaServer;\n\n        public bool UseChinaServer\n        {\n            get => _useChinaServer;\n            set\n            {\n                Preferences.Set(PreferencesKeys.UseChinaServer, value);\n                SetProperty(ref _useChinaServer, value);\n            }\n        }\n\n        private bool _showDebugInfo;\n\n        public bool ShowDebugInfo\n        {\n            get => _showDebugInfo;\n            set\n            {\n                Preferences.Set(PreferencesKeys.ShowDebugInfo, value);\n                SetProperty(ref _showDebugInfo, value);\n            }\n        }\n\n        private bool _hideAds;\n\n        public bool HideAds\n        {\n            get => _hideAds;\n            set\n            {\n                Preferences.Set(PreferencesKeys.HideAds, value);\n                SetProperty(ref _hideAds, value);\n            }\n        }\n\n        public void SexRadioSetToMale()\n        {\n            this.Sex = Sex.Male;\n        }\n\n        public void SexRadioSetToFemale()\n        {\n            this.Sex = Sex.Female;\n        }\n\n        public void ScaleTypeSetToBodyCompositionScale()\n        {\n            this.ScaleType = ScaleType.MiBodyCompositionScale;\n        }\n\n         public void ScaleTypeSetToMiscale()\n        {\n            this.ScaleType = ScaleType.MiSmartScale;\n        }\n\n        public void ScaleTypeSetToS400()\n        {\n            this.ScaleType = ScaleType.S400;\n        }\n        \n\n        public void CheckPreferences()\n        {\n\n        }\n\n        private string _address;\n\n        public string Address\n        {\n            get => _address;\n            set\n            {\n                SetProperty(ref _address, value);\n                Preferences.Set(PreferencesKeys.MiScaleBluetoothAddress, value);\n            }\n        }\n\n        private string _bindkey;\n\n        public string Bindkey\n        {\n            get => _bindkey;\n            set\n            {\n                SetProperty(ref _bindkey, value);\n                Preferences.Set(PreferencesKeys.S400Bindkey, value);\n            }\n        }\n\n        private int _age;\n\n        public int Age\n        {\n            get\n            {\n                if (_useBirthDateMode)\n                {\n                    // Calculate age from birthday\n                    var today = DateTime.Today;\n                    var age = today.Year - _birthDate.Year;\n                    if (_birthDate.Date > today.AddYears(-age))\n                    {\n                        age--;\n                    }\n                    return age;\n                }\n                else\n                {\n                    // Return manually entered age\n                    return _manualAge;\n                }\n            }\n        }\n\n        private int _manualAge;\n\n        public string ManualAge\n        {\n            get => _manualAge.ToString();\n            set\n            {\n                if (value is null) return;\n                if (int.TryParse(value, out var result))\n                {\n                    SetProperty(ref _manualAge, result);\n                    if (result == 0) return;\n                    Preferences.Set(PreferencesKeys.UserAge, result);\n                    OnPropertyChanged(nameof(Age));\n                }\n            }\n        }\n\n        private bool _useBirthDateMode;\n\n        public bool UseBirthDateMode\n        {\n            get => _useBirthDateMode;\n            set\n            {\n                if (SetProperty(ref _useBirthDateMode, value))\n                {\n                    Preferences.Set(PreferencesKeys.UseBirthDateMode, value);\n                    OnPropertyChanged(nameof(Age));\n                }\n            }\n        }\n\n        private DateTime _birthDate;\n        private bool _isLoadingPreferences = false;\n\n        public DateTime BirthDate\n        {\n            get => _birthDate;\n            set\n            {\n                if (SetProperty(ref _birthDate, value))\n                {\n                    // Only save to preferences if we're not in the middle of loading\n                    if (!_isLoadingPreferences)\n                    {\n                        Preferences.Set(PreferencesKeys.UserBirthDate, value.Ticks);\n                        OnPropertyChanged(nameof(Age));\n                    }\n                }\n            }\n        }\n\n        private int _height;\n\n        public string Height\n        {\n            get => _height.ToString();\n            set\n            {\n                if (value is null) return;\n                if (int.TryParse(value, out var result))\n                {\n                    SetProperty(ref _height, result);\n                    if (result == 0) return;\n                    Preferences.Set(PreferencesKeys.UserHeight, result);\n                }\n            }\n        }\n\n        public bool IsMaleSelected\n        {\n            get => _sex == Sex.Male;\n        }\n\n        public bool IsFemaleSelected\n        {\n            get => _sex == Sex.Female;\n        }\n\n        private Sex _sex;\n\n        public Sex Sex\n        {\n            get => _sex;\n            set\n            {\n                if (_sex == value) return;\n                SetProperty(ref _sex, value);\n                Preferences.Set(PreferencesKeys.UserSex, (byte)value);\n            }\n        }\n\n\n\n        public bool IsMiBodyCompositionScaleSelected\n        {\n            get => _scaleType == ScaleType.MiBodyCompositionScale;\n        }\n\n        public bool IsMiSmartScaleSelected\n        {\n            get => _scaleType == ScaleType.MiSmartScale;\n        }\n\n        public bool IsS400Selected\n        {\n            get => _scaleType == ScaleType.S400;\n        }\n\n        private ScaleType _scaleType;\n\n        public ScaleType ScaleType\n        {\n            get => _scaleType;\n            set\n            {\n                if (_scaleType != value)\n                {\n                    SetProperty(ref _scaleType, value);\n                    Preferences.Set(PreferencesKeys.ScaleType, (byte)value);\n                }\n              \n            }\n        }\n\n        private string _email;\n\n        public string Email\n        {\n            get => _email;\n            set\n            {if(_email != value)\n                {\n                    SetProperty(ref _email, value);\n                    Preferences.Set(PreferencesKeys.GarminUserEmail, value);\n                    this._clearTokens();\n                }\n                \n            }\n        }\n\n        private string _password;\n\n        public string Password\n        {\n            get => _password;\n            set\n            {\n                if(_password != value)\n                {\n                    SetProperty(ref _password, value);\n                    SecureStorage.SetAsync(PreferencesKeys.GarminUserPassword, value);\n                    this._clearTokens();\n                }\n               \n            }\n        }\n\n        private void _clearTokens()\n        {\n            SecureStorage.SetAsync(PreferencesKeys.GarminUserAccessToken, string.Empty);\n            SecureStorage.SetAsync(PreferencesKeys.GarminUserTokenSecret, string.Empty);\n        }\n\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Views/AboutPage.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<ContentPage\n    x:Class=\"MiScaleExporter.MAUI.Views.AboutPage\"\n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n    xmlns:admob=\"clr-namespace:Plugin.AdMob;assembly=Plugin.AdMob\"\n    xmlns:localization=\"clr-namespace:MiScaleExporter.MAUI.Resources.Localization\"\n    xmlns:vm=\"clr-namespace:MiScaleExporter.MAUI.ViewModels\"\n    Title=\"{Binding Title}\">\n\n    <ContentPage.Resources />\n\n    <Grid>\n        <Grid.RowDefinitions>\n            <RowDefinition Height=\"Auto\" />\n            <RowDefinition Height=\"*\" />\n            <RowDefinition Height=\"Auto\" />\n        </Grid.RowDefinitions>\n        <admob:BannerAd Grid.Row=\"0\"\nx:Name=\"adMobBanner\"\nAdUnitId=\"ca-app-pub-1938975042085430/4160336701\"\nAdSize=\"Banner\"\n />\n        <ScrollView Grid.Row=\"1\">\n\n                <StackLayout\n                Padding=\"15,24,15,24\"\n                Orientation=\"Vertical\"\n                Spacing=\"10\">\n\n                    <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.AboutGarmin}\" />\n                    <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.AboutMeasureInstruction}\" />\n                    <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.AboutUpload}\" />\n                    <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.AboutMFAAndStoringData}\" />\n                </StackLayout>\n        </ScrollView>\n        <ScrollView Grid.Row=\"2\">\n            <StackLayout\n                Padding=\"15,24,15,24\"\n                Orientation=\"Vertical\"\n                Spacing=\"10\">\n\n                <Button\n                    Margin=\"0,10,0,0\"\n                    BackgroundColor=\"{StaticResource Primary}\"\n                    Command=\"{Binding GoToScanCommand}\"\n                    Text=\"{x:Static localization:AppSnippets.GoToScan}\"\n                    TextColor=\"White\" />\n                <Button\n                    Margin=\"0,10,0,0\"\n                    BackgroundColor=\"{StaticResource Primary}\"\n                    Command=\"{Binding OpenHelpCommand}\"\n                    Text=\"{x:Static localization:AppSnippets.OpenHelp}\"\n                    TextColor=\"White\" />\n                <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.DoYouLikeAndWouldYouLikeToSupport}\" />\n                <ImageButton\n                    Margin=\"0,10,0,0\"\n                    Command=\"{Binding OpenCoffeeCommand}\"\n                    Source=\"Images/buymeacoffe.png\"\n                    HeightRequest=\"50\"\n                    />\n                <Button\n                    Margin=\"0,10,0,0\"\n                    BackgroundColor=\"{StaticResource Primary}\"\n                    Command=\"{Binding OpenGithubCommand}\"\n                    Text=\"{x:Static localization:AppSnippets.VisitProjectRepository}\"\n                    TextColor=\"White\" />\n                \n\n            </StackLayout>\n        </ScrollView>\n    </Grid>\n\n</ContentPage>\n"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Views/AboutPage.xaml.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Autofac;\nusing MiScaleExporter.MAUI;\nusing MiScaleExporter.MAUI.ViewModels;\nusing MiScaleExporter.Models;\n\nnamespace MiScaleExporter.MAUI.Views\n{\n    [XamlCompilation(XamlCompilationOptions.Compile)]\n    public partial class AboutPage : ContentPage\n    {\n        public AboutPage()\n        {\n            InitializeComponent();\n            using (var scope = App.Container.BeginLifetimeScope())\n            {\n                this.BindingContext = scope.Resolve<AboutViewModel>();\n            }\n        }\n\n        protected override void OnAppearing()\n        {\n            this.adMobBanner.IsVisible = !Preferences.Get(PreferencesKeys.HideAds, false);\n        }\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Views/FormPage.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n\n<ContentPage\n    x:Class=\"MiScaleExporter.MAUI.Views.FormPage\"\n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n    xmlns:behaviors=\"clr-namespace:MiScaleExporter.MAUI.Behaviors;assembly=MiScaleExporter.MAUI\"\n    xmlns:admob=\"clr-namespace:Plugin.AdMob;assembly=Plugin.AdMob\"\n    xmlns:localization=\"clr-namespace:MiScaleExporter.MAUI.Resources.Localization\"\n    xmlns:toolkit=\"http://schemas.microsoft.com/dotnet/2022/maui/toolkit\"\n    Title=\"{Binding Title}\">\n\n    <ContentPage.Resources>\n        <Style x:Key=\"InvalidEntryStyle\" TargetType=\"Entry\">\n            <Setter Property=\"TextColor\" Value=\"Red\" />\n        </Style>\n    </ContentPage.Resources>\n\n\n\n    <AbsoluteLayout HorizontalOptions=\"FillAndExpand\">\n        <ScrollView HorizontalOptions=\"FillAndExpand\" VerticalScrollBarVisibility=\"Always\"\n                       AbsoluteLayout.LayoutBounds=\"0,0,1,1\"\n                        AbsoluteLayout.LayoutFlags=\"All\"\n               >\n            <StackLayout  Orientation=\"Vertical\"  HorizontalOptions=\"FillAndExpand\">\n                <admob:BannerAd\nx:Name=\"adMobBanner\"\nAdUnitId=\"ca-app-pub-1938975042085430/4160336701\"\nAdSize=\"SmartBanner\"\n />\n                <StackLayout Orientation=\"Vertical\" HorizontalOptions=\"FillAndExpand\">\n                    <Grid  \n                Padding=\"10,10,10,10\"\n                HorizontalOptions=\"FillAndExpand\">\n                        <Grid.RowDefinitions>\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"*\" />\n                        </Grid.RowDefinitions>\n                        <Grid.ColumnDefinitions>\n                            <ColumnDefinition Width=\"50*\" />\n                            <ColumnDefinition Width=\"50*\" />\n                        </Grid.ColumnDefinitions>\n\n                        <StackLayout\n                            Grid.Row=\"0\"\n                            Grid.Column=\"0\"\n                            Grid.ColumnSpan=\"2\"\n                            Padding=\"10\"\n                            Orientation=\"Vertical\">\n                            \n                        </StackLayout>\n\n                        <StackLayout Grid.Row=\"1\" Grid.Column=\"0\" >\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.WeightKg}\" IsVisible=\"{Binding ShowWeightInKg}\"/>\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.WeightLbs}\" IsVisible=\"{Binding ShowWeightInLbs}\" />\n                            <Entry\n                        FontSize=\"Medium\"\n                        Keyboard=\"Numeric\"\n                        Text=\"{Binding Weight, Mode=TwoWay, StringFormat='{0:0.##}'}\">\n                                <Entry.Behaviors>\n                                    <behaviors:NumericDoubleValidationBehavior />\n                                </Entry.Behaviors>\n                            </Entry>\n                        </StackLayout>\n\n                        <StackLayout Grid.Row=\"1\" Grid.Column=\"1\" >\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.BMI}\" />\n                            <Entry\n                        FontSize=\"Medium\"\n                        Keyboard=\"Numeric\"\n                        Text=\"{Binding BMI, Mode=TwoWay}\">\n                                <Entry.Behaviors>\n                                    <behaviors:NumericDoubleValidationBehavior />\n                                </Entry.Behaviors>\n                            </Entry>\n                        </StackLayout>\n                       \n\n                        <StackLayout Grid.Row=\"2\" Grid.Column=\"0\">\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.BodyFatPercent}\" />\n\n                            <Entry\n                        FontSize=\"Medium\"\n                        Keyboard=\"Numeric\"\n                        Text=\"{Binding Fat, Mode=TwoWay}\">\n                                <Entry.Behaviors>\n                                    <behaviors:NumericDoubleValidationBehavior />\n                                </Entry.Behaviors>\n                            </Entry>\n                        </StackLayout>\n                        <StackLayout Grid.Row=\"2\" Grid.Column=\"1\">\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.MuscleMassLbs}\" IsVisible=\"{Binding MuscleMassAsLbs}\" />\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.MuscleMassKg}\" IsVisible=\"{Binding MuscleMassAsKg}\" />\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.MuscleMassPer}\" IsVisible=\"{Binding MuscleMassAsPercentage}\" />\n                            <Entry\n                        FontSize=\"Medium\"\n                        Keyboard=\"Numeric\"\n                        Text=\"{Binding MuscleMass, Mode=TwoWay}\">\n                                <Entry.Behaviors>\n                                    <behaviors:NumericDoubleValidationBehavior />\n                                </Entry.Behaviors>\n                            </Entry>\n                        </StackLayout>\n\n                        <StackLayout Grid.Row=\"3\" Grid.Column=\"0\">\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.WaterPercent}\" />\n\n                            <Entry\n                        FontSize=\"Medium\"\n                        Keyboard=\"Numeric\"\n                        Text=\"{Binding WaterPercentage, Mode=TwoWay}\">\n                                <Entry.Behaviors>\n                                    <behaviors:NumericDoubleValidationBehavior />\n                                </Entry.Behaviors>\n                            </Entry>\n\n                        </StackLayout>\n                        <StackLayout Grid.Row=\"3\" Grid.Column=\"1\">\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.BoneMassPercent}\" IsVisible=\"{Binding ShowWeightInKg}\"/>\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.BoneMassLbs}\" IsVisible=\"{Binding ShowWeightInLbs}\" />\n                            <Entry\n                        FontSize=\"Medium\"\n                        Keyboard=\"Numeric\"\n                        Text=\"{Binding BoneMass, Mode=TwoWay}\">\n                                <Entry.Behaviors>\n                                    <behaviors:NumericDoubleValidationBehavior />\n                                </Entry.Behaviors>\n                            </Entry>\n\n                        </StackLayout>\n\n                        <StackLayout Grid.Row=\"4\" Grid.Column=\"0\">\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.VisceralFat}\" />\n\n                            <Entry\n                        FontSize=\"Medium\"\n                        Keyboard=\"Numeric\"\n                        Text=\"{Binding VisceralFat, Mode=TwoWay}\">\n                                <Entry.Behaviors>\n                                    <behaviors:NumericDoubleValidationBehavior />\n                                </Entry.Behaviors>\n                            </Entry>\n\n                        </StackLayout>\n                        <StackLayout Grid.Row=\"4\" Grid.Column=\"1\">\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.BodyAgeYears}\" />\n\n                            <Entry\n                        FontSize=\"Medium\"\n                        Keyboard=\"Numeric\"\n                        Text=\"{Binding MetabolicAge, Mode=TwoWay}\">\n                                <Entry.Behaviors>\n                                    <behaviors:NumericDoubleValidationBehavior />\n                                </Entry.Behaviors>\n                            </Entry>\n\n                        </StackLayout>\n\n                        <StackLayout Grid.Row=\"5\" Grid.Column=\"0\">\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.BodyType}\" />\n\n                            <Entry\n                        FontSize=\"Medium\"\n                        Keyboard=\"Numeric\"\n                        Text=\"{Binding BodyType, Mode=TwoWay}\">\n                                <Entry.Behaviors>\n                                    <behaviors:NumericIntValidationBehavior />\n                                </Entry.Behaviors>\n                            </Entry>\n\n                        </StackLayout>\n\n                        <StackLayout Grid.Row=\"5\" Grid.Column=\"1\">\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.TimeOfMeasurement}\" />\n\n                            <StackLayout Orientation=\"Horizontal\">\n\n                                <DatePicker\n                            Date=\"{Binding Date}\"\n                            FontSize=\"Medium\"\n                            Format=\"d\" />\n                                <TimePicker\n                            FontSize=\"Medium\"\n                            Format=\"HH:mm\"\n                            Time=\"{Binding Time}\" />\n                            </StackLayout>\n\n                        </StackLayout>\n\n\n                        <StackLayout\n                    Grid.Row=\"6\"\n                    Grid.Column=\"0\"\n                    Grid.ColumnSpan=\"2\"\n                    IsVisible=\"{Binding ShowEmail}\">\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.Email}\" />\n\n                            <Entry\n                        FontSize=\"Medium\"\n                        Keyboard=\"Email\"\n                        Text=\"{Binding Email, Mode=TwoWay}\">\n                                <Entry.Behaviors>\n                                    <toolkit:EmailValidationBehavior DecorationFlags=\"Trim\" InvalidStyle=\"{StaticResource InvalidEntryStyle}\" />\n                                </Entry.Behaviors>\n                            </Entry>\n\n                        </StackLayout>\n\n                        <StackLayout\n                    Grid.Row=\"7\"\n                    Grid.Column=\"0\"\n                    Grid.ColumnSpan=\"2\"\n                    IsVisible=\"{Binding ShowPassword}\">\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.Password}\" />\n\n                            <Entry\n                        FontSize=\"Medium\"\n                        IsPassword=\"True\"\n                        Text=\"{Binding Password, Mode=TwoWay}\" />\n\n                        </StackLayout>\n                        <StackLayout\n        Grid.Row=\"8\"\n        Grid.Column=\"0\"\n        Grid.ColumnSpan=\"2\"\n        IsVisible=\"{Binding ShowMFACode}\">\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.MFACode}\" />\n\n                            <Entry\n            FontSize=\"Medium\"\n            Text=\"{Binding MFACode, Mode=TwoWay}\" />\n\n                        </StackLayout>\n\n\n\n                        <StackLayout\n                    Grid.Row=\"9\"\n                    Grid.Column=\"0\"\n                    Grid.ColumnSpan=\"2\"\n                    Padding=\"10\"\n                    Orientation=\"Vertical\">\n                            <Button\n                                Margin=\"0,10,0,0\"\n                                BackgroundColor=\"{StaticResource Primary}\"\n                                Command=\"{Binding UploadCommand}\"\n                                Text=\"{x:Static localization:AppSnippets.UploadToGarminCloud}\"\n                                TextColor=\"White\" />\n                            <Button\n                                Margin=\"0,10,0,0\"\n                                BackgroundColor=\"{StaticResource Primary}\"\n                                Command=\"{Binding GenerateFitFileCommand}\"\n                                Text=\"{x:Static localization:AppSnippets.GenerateOnlyFitFile}\"\n                                TextColor=\"White\" /> \n\n                            <Button\n                                Margin=\"0,10,0,0\"\n                                BackgroundColor=\"{StaticResource DarkRed}\"\n                                Command=\"{Binding CancelMFACommand}\"\n                                Text=\"{x:Static localization:AppSnippets.CancelMFARequest}\"\n                                TextColor=\"White\" \n                                IsVisible=\"{Binding ShowMFACode}\"/>\n\n                            <StackLayout IsVisible=\"{Binding IsAutomaticCalculation}\">\n                                <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.ValuesThatWillNotBeSentToTheCloud}\" />\n                                <StackLayout Orientation=\"Horizontal\">\n                                    <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.ProteinPercent}\" />\n                                    <Label FontSize=\"Small\" Text=\"{Binding ProteinPercentage, Mode=TwoWay}\" />\n\n                                </StackLayout>\n                                <StackLayout Orientation=\"Horizontal\">\n                                    <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.BasalMetabolosimKCal}\" />\n                                    <Label FontSize=\"Small\" Text=\"{Binding BMR, Mode=TwoWay}\" />\n                                </StackLayout>\n                                <StackLayout Orientation=\"Horizontal\">\n                                    <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.IdealWeightKg}\" IsVisible=\"{Binding ShowWeightInKg}\" />\n                                    <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.IdealWeightLbs}\" IsVisible=\"{Binding ShowWeightInLbs}\" />\n                                    <Label FontSize=\"Small\" Text=\"{Binding IdealWeight, Mode=TwoWay}\" />\n\n                                </StackLayout>\n                            </StackLayout>\n\n\n                        </StackLayout>\n\n\n                    </Grid>\n\n\n                </StackLayout>\n\n            </StackLayout>\n        </ScrollView>\n        <StackLayout\nPadding=\"12\"\nAbsoluteLayout.LayoutBounds=\"0.5,0.4,-1,-1\"\nAbsoluteLayout.LayoutFlags=\"PositionProportional\"\nIsVisible=\"{Binding IsBusyForm}\">\n            <Frame>\n                <StackLayout>\n                    <ActivityIndicator\nBackgroundColor=\"White\"\nIsRunning=\"{Binding IsBusyForm}\"\nColor=\"#80000000\" />\n\n                    <Label\nHorizontalOptions=\"Center\"\nText=\"{x:Static localization:AppSnippets.Uploading}\"\nTextColor=\"Black\" />\n                </StackLayout>\n\n            </Frame>\n\n        </StackLayout>\n    </AbsoluteLayout>\n\n\n</ContentPage>"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Views/FormPage.xaml.cs",
    "content": "﻿\nusing Autofac;\n\nusing MiScaleExporter.MAUI.ViewModels;\nusing MiScaleExporter.Models;\n\nnamespace MiScaleExporter.MAUI.Views\n{\n    [QueryProperty(nameof(AutoUpload), \"autoUpload\")]\n    [XamlCompilation(XamlCompilationOptions.Compile)]\n    public partial class FormPage : ContentPage\n    {\n        private IFormViewModel vm;\n        public FormPage()\n        {\n            InitializeComponent();\n            using (var scope = App.Container.BeginLifetimeScope())\n            {\n                this.BindingContext = vm = scope.Resolve<IFormViewModel>();\n            }\n        }\n\n        protected override async void OnAppearing()\n        {\n            base.OnAppearing();\n            this.adMobBanner.IsVisible = !Preferences.Get(PreferencesKeys.HideAds, false);\n            await vm.LoadPreferencesAsync();\n            vm.LoadBodyComposition();\n        }\n\n        public bool AutoUpload\n        {\n            set\n            {\n                if (value)\n                {\n                    vm.AutoUpload();\n                }\n            }\n        }\n      \n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Views/HelpPage.xaml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<ContentPage\n    x:Class=\"MiScaleExporter.MAUI.Views.HelpPage\"\n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n    xmlns:localization=\"clr-namespace:MiScaleExporter.MAUI.Resources.Localization\"\n    Title=\"{x:Static localization:AppSnippets.Help}\">\n    <ScrollView VerticalScrollBarVisibility=\"Always\">\n        <StackLayout\n            Padding=\"15,24,15,24\"\n            Orientation=\"Vertical\"\n            Spacing=\"10\">\n            <Label\n                FontAttributes=\"Bold\"\n                FontSize=\"Small\"\n                Text=\"{x:Static localization:AppSnippets.HelpConnect}\" />\n            <Label FontSize=\"Small\" \n                   Text=\"Instruction for the S400 scale (click here)\"\n                   TextDecorations=\"Underline\"\n                   TextColor=\"#007CC3\"\n                   Padding=\"15,0,0,0\">\n                <Label.GestureRecognizers>\n                    <TapGestureRecognizer Command=\"{Binding S400HelpCommand}\" />\n                </Label.GestureRecognizers>\n            </Label>\n\n            <Label\n                Padding=\"15,0,0,0\"\n                FontSize=\"Small\"\n                Text=\"{x:Static localization:AppSnippets.HelpConnectDescription}\" />\n            <Label\n                Padding=\"15,0,0,0\"\n                FontSize=\"Small\"\n                Text=\"{x:Static localization:AppSnippets.HelpConnectDescription2}\" />\n            <Image Source=\"Images/xiaomi.jpg\" />\n            <Label\n                FontAttributes=\"Bold\"\n                FontSize=\"Small\"\n                Text=\"{x:Static localization:AppSnippets.HelpHowItWorks}\" />\n            <Label\n                Padding=\"15,0,0,0\"\n                FontSize=\"Small\"\n                Text=\"{x:Static localization:AppSnippets.HelpHowItWorksDescription}\" />\n            <Label\n                FontAttributes=\"Bold\"\n                FontSize=\"Small\"\n                Text=\"{x:Static localization:AppSnippets.HelpStrangeResults}\" />\n            <Label\n                Padding=\"15,0,0,0\"\n                FontSize=\"Small\"\n                Text=\"{x:Static localization:AppSnippets.HelpStrangeResultsDescription}\" />\n            <Label\n                FontAttributes=\"Bold\"\n                FontSize=\"Small\"\n                Text=\"{x:Static localization:AppSnippets.HelpZeppLifeDriference}\" />\n            <Label\n                Padding=\"15,0,0,0\"\n                FontSize=\"Small\"\n                Text=\"{x:Static localization:AppSnippets.HelpZeppLifeDriferenceDescription}\" />\n            <Label\n                FontAttributes=\"Bold\"\n                FontSize=\"Small\"\n                Text=\"{x:Static localization:AppSnippets.HelpExternalApi}\" />\n            <Label\n                Padding=\"15,0,0,0\"\n                FontSize=\"Small\"\n                Text=\"{x:Static localization:AppSnippets.HelpExternalApiDescription}\" />\n\n            <Label\n                FontAttributes=\"Bold\"\n                FontSize=\"Small\"\n                Text=\"{x:Static localization:AppSnippets.HelpGarminAndXiaomi}\" />\n            <Label\n                Padding=\"15,0,0,0\"\n                FontSize=\"Small\"\n                Text=\"{x:Static localization:AppSnippets.HelpGarminAndXiaomiDescription}\" />\n            <Label\n                FontAttributes=\"Bold\"\n                FontSize=\"Small\"\n                Text=\"{x:Static localization:AppSnippets.HelpFeedback}\" />\n            <Label\n                Padding=\"15,0,0,0\"\n                FontSize=\"Small\"\n                Text=\"{x:Static localization:AppSnippets.HelpFeedbackDescription}\" />\n            <Button\n                Margin=\"0,10,0,0\"\n                BackgroundColor=\"{StaticResource Primary}\"\n                Command=\"{Binding OpenGithubCommand}\"\n                Text=\"{x:Static localization:AppSnippets.VisitProjectRepository}\"\n                TextColor=\"White\" />\n            <Label\n                FontAttributes=\"Bold\"\n                FontSize=\"Small\"\n                Text=\"{x:Static localization:AppSnippets.HelpCoffee}\" />\n            <Label\n                Padding=\"15,0,0,0\"\n                FontSize=\"Small\"\n                Text=\"{x:Static localization:AppSnippets.HelpCoffeeDescription}\" />\n\n            <Button\n                Margin=\"0,10,0,0\"\n                BackgroundColor=\"{StaticResource Primary}\"\n                Command=\"{Binding OpenCoffeeCommand}\"\n                Text=\"{x:Static localization:AppSnippets.BuyMeACoffee}\"\n                TextColor=\"White\" />\n\n            <Label\n                Margin=\"10\"\n                FontSize=\"Small\"\n                HorizontalOptions=\"Center\"\n                Text=\"{x:Static localization:AppSnippets.CreatedBy}\" />\n        </StackLayout>\n    </ScrollView>\n</ContentPage>"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Views/HelpPage.xaml.cs",
    "content": "using System.Windows.Input;\n\nnamespace MiScaleExporter.MAUI.Views;\n\npublic partial class HelpPage : ContentPage\n{\n    public ICommand OpenGithubCommand { get; }\n    public ICommand OpenCoffeeCommand { get; }\n    public ICommand S400HelpCommand { get; } = new Command(async () =>\n        await Launcher.OpenAsync(\"https://lswiderski.github.io/mi-scale-exporter/#steps-to-connect-xiaomi-body-composition-scale-s400\"));\n\n    public HelpPage()\n\t{\n\n        this.BindingContext = this;\n        OpenGithubCommand = new Command(async () =>\n         await Browser.OpenAsync(\"https://github.com/lswiderski/mi-scale-exporter\"));\n        OpenCoffeeCommand = new Command(async () =>\n            await Browser.OpenAsync(\"https://www.buymeacoffee.com/lukaszswiderski\"));\n\n        InitializeComponent();\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Views/ScalePage.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n\n<ContentPage\n    x:Class=\"MiScaleExporter.MAUI.Views.ScalePage\"\n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n    xmlns:behaviors=\"clr-namespace:MiScaleExporter.MAUI.Behaviors;assembly=MiScaleExporter.MAUI\"\n    xmlns:admob=\"clr-namespace:Plugin.AdMob;assembly=Plugin.AdMob\"\n    xmlns:localization=\"clr-namespace:MiScaleExporter.MAUI.Resources.Localization\"\n    xmlns:models=\"clr-namespace:MiScaleExporter.Models\"\n    xmlns:vm=\"clr-namespace:MiScaleExporter.MAUI.ViewModels\"\n    Title=\"{Binding Title}\">\n    <AbsoluteLayout HorizontalOptions=\"FillAndExpand\" VerticalOptions=\"FillAndExpand\">\n        <Grid\n            AbsoluteLayout.LayoutBounds=\"0,0,1,1\"\n            AbsoluteLayout.LayoutFlags=\"All\"\n            HorizontalOptions=\"FillAndExpand\">\n            <Grid.RowDefinitions>\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"*\" />\n            </Grid.RowDefinitions>\n            <Grid.ColumnDefinitions>\n                <ColumnDefinition Width=\"*\" />\n            </Grid.ColumnDefinitions>\n            <admob:BannerAd\nx:Name=\"adMobBanner\" Grid.Row=\"0\"\nAdUnitId=\"ca-app-pub-1938975042085430/4160336701\"\nAdSize=\"SmartBanner\"\n />\n            <StackLayout\n                Grid.Row=\"1\"\n                HorizontalOptions=\"Center\"\n                Orientation=\"Horizontal\">\n              \n                <Label\n                    Margin=\"0,100,0,0\"\n                    FontSize=\"90\"\n                    Text=\"{Binding Source={x:Static models:ScaleMeasurement.Instance}, Path=Weight}\"\n                    VerticalOptions=\"CenterAndExpand\"\n                    VerticalTextAlignment=\"End\" />\n            </StackLayout>\n\n            <ScrollView Grid.Row=\"2\" HorizontalOptions=\"FillAndExpand\">\n                <StackLayout\n                    Padding=\"15,24,15,24\"\n                    Orientation=\"Vertical\"\n                    Spacing=\"10\"\n                    VerticalOptions=\"EndAndExpand\">\n                    <Label FontSize=\"Small\" Text=\"{Binding Source={x:Static models:ScaleMeasurement.Instance}, Path=FoundScale}\" />\n                    <Label FontSize=\"Small\" Text=\"{Binding Source={x:Static models:ScaleMeasurement.Instance}, Path=DebugData}\" />\n                    <Label FontSize=\"Small\" Text=\"{Binding Source={x:Static models:ScaleMeasurement.Instance}, Path=RawData}\" />\n\n                    <Label FontSize=\"Small\" Text=\"{Binding ScanningLabel}\" />\n\n                    <Button\n                        Margin=\"0,10,0,0\"\n                        BackgroundColor=\"{StaticResource Primary}\"\n                        Command=\"{Binding StopCommand}\"\n                        Text=\"{x:Static localization:AppSnippets.StopMeasure}\"\n                        TextColor=\"White\" />\n                    <Button\n                        Margin=\"0,10,0,0\"\n                        BackgroundColor=\"{StaticResource Primary}\"\n                        Command=\"{Binding CancelCommand}\"\n                        Text=\"{x:Static localization:AppSnippets.CancelSearch}\"\n                        TextColor=\"White\" />\n                    \n                </StackLayout>\n            </ScrollView>\n        </Grid>\n        <StackLayout\n            Padding=\"12\"\n            AbsoluteLayout.LayoutBounds=\"0.5,0.5,-1,-1\"\n            AbsoluteLayout.LayoutFlags=\"PositionProportional\"\n            IsVisible=\"{Binding IsBusyForm}\">\n            <Frame>\n                <StackLayout>\n                    <ActivityIndicator\n                        BackgroundColor=\"White\"\n                        IsRunning=\"{Binding IsBusyForm}\"\n                        Color=\"#80000000\" />\n\n                    <Label\n                        HorizontalOptions=\"Center\"\n                        Text=\"{x:Static localization:AppSnippets.Scanning}\"\n                        TextColor=\"Black\" />\n                </StackLayout>\n\n            </Frame>\n\n\n        </StackLayout>\n    </AbsoluteLayout>\n</ContentPage>"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Views/ScalePage.xaml.cs",
    "content": "﻿\nusing Autofac;\nusing MiScaleExporter.Models;\nusing MiScaleExporter.MAUI.ViewModels;\n\n\nnamespace MiScaleExporter.MAUI.Views\n{\n    public partial class ScalePage : ContentPage\n    {\n        private IScaleViewModel vm;\n        public ScalePage()\n        {\n            InitializeComponent();\n            using (var scope = App.Container.BeginLifetimeScope())\n            {\n                this.BindingContext = vm = scope.Resolve<IScaleViewModel>();\n            }\n        }\n\n        protected override async void OnAppearing()\n        {\n            base.OnAppearing();\n            this.adMobBanner.IsVisible = !Preferences.Get(PreferencesKeys.HideAds, false);\n            await vm.CheckPreferencesAsync();\n        }\n\n    }\n}"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Views/SettingsPage.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<ContentPage\n    x:Class=\"MiScaleExporter.MAUI.Views.SettingPage\"\n    xmlns=\"http://schemas.microsoft.com/dotnet/2021/maui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\n    xmlns:behaviors=\"clr-namespace:MiScaleExporter.MAUI.Behaviors;assembly=MiScaleExporter.MAUI\"\n    xmlns:localization=\"clr-namespace:MiScaleExporter.MAUI.Resources.Localization\"\n    xmlns:toolkit=\"http://schemas.microsoft.com/dotnet/2022/maui/toolkit\"\n    xmlns:vm=\"clr-namespace:MiScaleExporter.MAUI.ViewModels\"\n    Title=\"{Binding Title}\">\n    <AbsoluteLayout HorizontalOptions=\"FillAndExpand\" VerticalOptions=\"FillAndExpand\">\n        <Grid\n            AbsoluteLayout.LayoutBounds=\"0,0,1,1\"\n            AbsoluteLayout.LayoutFlags=\"All\"\n            HorizontalOptions=\"FillAndExpand\">\n            <Grid.RowDefinitions>\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"*\" />\n            </Grid.RowDefinitions>\n            <Grid.ColumnDefinitions>\n                <ColumnDefinition Width=\"*\" />\n            </Grid.ColumnDefinitions>\n            <ScrollView Grid.Row=\"1\" HorizontalOptions=\"FillAndExpand\">\n                <StackLayout\n                    Padding=\"15,24,15,24\"\n                    Orientation=\"Vertical\"\n                    Spacing=\"20\">\n                    <Border>\n                        <Border.StrokeShape>\n                            <RoundRectangle CornerRadius=\"20\" />\n                        </Border.StrokeShape>\n                        <StackLayout\n                            Padding=\"15,24,15,24\"\n                            Orientation=\"Vertical\"\n                            Spacing=\"10\">\n                            <Label\n                                FontAttributes=\"Bold\"\n                                FontSize=\"Small\"\n                                Text=\"{x:Static localization:AppSnippets.ScaleSettings}\" />\n                            <BoxView\n                                HeightRequest=\"2\"\n                                HorizontalOptions=\"Fill\"\n                                Color=\"Gray\" />\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.Age}\" />\n                            <HorizontalStackLayout Spacing=\"20\">\n                                <StackLayout Orientation=\"Horizontal\" Spacing=\"10\" HorizontalOptions=\"FillAndExpand\">\n                                    <RadioButton\n                                        GroupName=\"AgeMode\"\n                                        IsChecked=\"{Binding UseBirthDateMode, Converter={StaticResource InvertedBoolConverter}}\"\n                                        VerticalOptions=\"Center\"\n                                         Content=\"Enter age manually\"/>\n                                </StackLayout>\n                                <StackLayout Orientation=\"Horizontal\" Spacing=\"10\" HorizontalOptions=\"FillAndExpand\">\n                                    <RadioButton\n                                        GroupName=\"AgeMode\"\n                                        IsChecked=\"{Binding UseBirthDateMode}\"\n                                        VerticalOptions=\"Center\" \n                                        Content=\"Use birth date\"/>\n                                   \n                                </StackLayout>\n                            </HorizontalStackLayout>\n\n                            <StackLayout IsVisible=\"{Binding UseBirthDateMode, Converter={StaticResource InvertedBoolConverter}}\">\n                                <Entry\n                                    FontSize=\"Medium\"\n                                    Keyboard=\"Numeric\"\n                                    Text=\"{Binding ManualAge, Mode=TwoWay}\">\n                                    <Entry.Behaviors>\n                                        <behaviors:NumericIntValidationBehavior />\n                                    </Entry.Behaviors>\n                                </Entry>\n                            </StackLayout>\n\n                            <StackLayout IsVisible=\"{Binding UseBirthDateMode}\">\n                                <DatePicker\n                                    FontSize=\"Medium\"\n                                    Date=\"{Binding BirthDate, Mode=TwoWay}\"\n                                    Format=\"dd/MM/yyyy\" />\n                                <StackLayout Orientation=\"Horizontal\" Spacing=\"10\">\n                                    <Label \n                                        FontSize=\"Small\" \n                                        Text=\"Your age:\"\n                                        VerticalOptions=\"Center\" />\n                                    <Label \n                                        FontSize=\"Medium\" \n                                        Text=\"{Binding Age}\"\n                                        VerticalOptions=\"Center\"\n                                        FontAttributes=\"Bold\" />\n                                    <Label \n                                        FontSize=\"Small\" \n                                        Text=\"years old\"\n                                        VerticalOptions=\"Center\" />\n                                </StackLayout>\n                            </StackLayout>\n\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.Height}\" />\n                            <Entry\n                                FontSize=\"Medium\"\n                                Keyboard=\"Numeric\"\n                                Text=\"{Binding Height, Mode=TwoWay}\">\n                                <Entry.Behaviors>\n                                    <behaviors:NumericIntValidationBehavior />\n                                </Entry.Behaviors>\n                            </Entry>\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.Sex}\" />\n                            <HorizontalStackLayout>\n                                <RadioButton\n                                    CheckedChanged=\"SexRadioSetToFemale\"\n                                    Content=\"{x:Static localization:AppSnippets.Female}\"\n                                    GroupName=\"Sex\"\n                                    IsChecked=\"{Binding IsFemaleSelected}\"\n                                    Value=\"0\" />\n                                <RadioButton\n                                    CheckedChanged=\"SexRadioSetToMale\"\n                                    Content=\"{x:Static localization:AppSnippets.Male}\"\n                                    GroupName=\"Sex\"\n                                    IsChecked=\"{Binding IsMaleSelected}\"\n                                    Value=\"1\" />\n                            </HorizontalStackLayout>\n\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.ScaleModel}\" />\n                            <RadioButton\n                                CheckedChanged=\"ScaleTypeSetToBodyCompositionScale\"\n                                Content=\"{x:Static localization:AppSnippets.MiBodyCompositionScale}\"\n                                GroupName=\"ScaleType\"\n                                IsChecked=\"{Binding IsMiBodyCompositionScaleSelected}\"\n                                Value=\"0\" />\n                            <RadioButton\n                                CheckedChanged=\"ScaleTypeSetToMiscale\"\n                                Content=\"{x:Static localization:AppSnippets.MiScale}\"\n                                GroupName=\"ScaleType\"\n                                IsChecked=\"{Binding IsMiSmartScaleSelected}\"\n                                Value=\"1\" />\n                            <RadioButton\n                                CheckedChanged=\"ScaleTypeSetToS400\"\n                                Content=\"Mi Scale S400\"\n                                GroupName=\"ScaleType\"\n                                IsChecked=\"{Binding IsS400Selected}\"\n                                Value=\"1\" />\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.BluetoothAddress}\" />\n                            <Entry FontSize=\"Medium\" Text=\"{Binding Address, Mode=TwoWay}\" />\n                       \n                            <StackLayout Orientation=\"Horizontal\" Spacing=\"10\">\n                                <Label FontSize=\"Small\" Text=\"BLE Key (S400 only)\" />\n                                <Label FontSize=\"Small\" Text=\"(how to get it)\"  TextDecorations=\"Underline\" TextColor=\"#007CC3\">\n\n                                    <Label.GestureRecognizers>\n                                        <TapGestureRecognizer Command=\"{Binding GetBLEKeyCommand}\" />\n                                    </Label.GestureRecognizers>\n                                </Label>\n                            </StackLayout>\n                            <Entry FontSize=\"Medium\" Text=\"{Binding Bindkey, Mode=TwoWay}\" />\n                        </StackLayout>\n\n                    </Border>\n                    <Border>\n                        <Border.StrokeShape>\n                            <RoundRectangle CornerRadius=\"20\" />\n                        </Border.StrokeShape>\n                        <StackLayout\n                            Padding=\"15,24,15,24\"\n                            Orientation=\"Vertical\"\n                            Spacing=\"10\">\n                            <Label\n                                FontAttributes=\"Bold\"\n                                FontSize=\"Small\"\n                                Text=\"{x:Static localization:AppSnippets.GarminSettings}\" />\n                            <BoxView\n                                HeightRequest=\"2\"\n                                HorizontalOptions=\"Fill\"\n                                Color=\"Gray\" />\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.Email}\" />\n                            <Entry\n                                FontSize=\"Medium\"\n                                Keyboard=\"Email\"\n                                Text=\"{Binding Email, Mode=TwoWay}\" />\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.Password}\" />\n                            <Entry\n                                FontSize=\"Medium\"\n                                IsPassword=\"True\"\n                                Text=\"{Binding Password, Mode=TwoWay}\" />\n\n                        </StackLayout>\n                    </Border>\n                    <Border>\n                        <Border.StrokeShape>\n                            <RoundRectangle CornerRadius=\"20\" />\n                        </Border.StrokeShape>\n                        <StackLayout\n                            Padding=\"15,24,15,24\"\n                            Orientation=\"Vertical\"\n                            Spacing=\"10\">\n                            <Label\n                                FontAttributes=\"Bold\"\n                                FontSize=\"Small\"\n                                Text=\"{x:Static localization:AppSnippets.AppSettings}\" />\n                            <BoxView\n                                HeightRequest=\"2\"\n                                HorizontalOptions=\"Fill\"\n                                Color=\"Gray\" />\n\n                            <Label FontSize=\"Small\" Text=\"{x:Static localization:AppSnippets.AlternateExternalAPIAddress}\" />\n                            <Entry FontSize=\"Medium\" Text=\"{Binding ApiAddress, Mode=TwoWay}\" />\n                            <Grid HorizontalOptions=\"FillAndExpand\" VerticalOptions=\"Start\">\n                                <Grid.RowDefinitions>\n                                    <RowDefinition Height=\"Auto\" />\n                                    <RowDefinition Height=\"Auto\" />\n                                    <RowDefinition Height=\"Auto\" />\n                                    <RowDefinition Height=\"Auto\" />\n                                    <RowDefinition Height=\"Auto\" />\n                                    <RowDefinition Height=\"Auto\" />\n                                    <RowDefinition Height=\"Auto\" />\n                                </Grid.RowDefinitions>\n\n                                <Grid.ColumnDefinitions>\n                                    <ColumnDefinition Width=\"auto\" />\n                                    <ColumnDefinition Width=\"*\" />\n                                </Grid.ColumnDefinitions>\n                                <CheckBox\n                                    Grid.Row=\"0\"\n                                    Grid.Column=\"0\"\n                                    IsChecked=\"{Binding UseExternalAPI, Mode=TwoWay}\"\n                                    VerticalOptions=\"Center\" />\n                                <Label\n                                    Grid.Row=\"0\"\n                                    Grid.Column=\"1\"\n                                    FontSize=\"Small\"\n                                    Text=\"{x:Static localization:AppSnippets.UseExternalAPI}\"\n                                    VerticalOptions=\"Center\" />\n                                <CheckBox\n                                    Grid.Row=\"1\"\n                                    Grid.Column=\"0\"\n                                    IsChecked=\"{Binding OneClickScanAndUpload, Mode=TwoWay}\"\n                                    VerticalOptions=\"Center\" />\n                                <Label\n                                    Grid.Row=\"1\"\n                                    Grid.Column=\"1\"\n                                    FontSize=\"Small\"\n                                    Text=\"{x:Static localization:AppSnippets.OneClickScanUpload}\"\n                                    VerticalOptions=\"Center\" />\n                                <CheckBox\n                                    Grid.Row=\"2\"\n                                    Grid.Column=\"0\"\n                                    IsChecked=\"{Binding ShowDebugInfo, Mode=TwoWay}\"\n                                    VerticalOptions=\"Center\" />\n                                <Label\n                                    Grid.Row=\"2\"\n                                    Grid.Column=\"1\"\n                                    FontSize=\"Small\"\n                                    Text=\"{x:Static localization:AppSnippets.ShowDebug}\"\n                                    VerticalOptions=\"Center\" />\n                                <CheckBox\n                                    Grid.Row=\"3\"\n                                    Grid.Column=\"0\"\n                                    IsChecked=\"{Binding MuscleMassAsPercentage, Mode=TwoWay}\"\n                                    VerticalOptions=\"Center\" />\n                                <Label\n                                    Grid.Row=\"3\"\n                                    Grid.Column=\"1\"\n                                    FontSize=\"Small\"\n                                    Text=\"{x:Static localization:AppSnippets.MuscleMassAsPercentage}\"\n                                    VerticalOptions=\"Center\" />\n                                <CheckBox\n                                    Grid.Row=\"4\"\n                                    Grid.Column=\"0\"\n                                    IsChecked=\"{Binding DisplayWeightInLbs, Mode=TwoWay}\"\n                                    VerticalOptions=\"Center\" />\n                                <Label\n                                    Grid.Row=\"4\"\n                                    Grid.Column=\"1\"\n                                    FontSize=\"Small\"\n                                    Text=\"Display weight in lbs\"\n                                    VerticalOptions=\"Center\" />\n                                <CheckBox\n                                    Grid.Row=\"5\"\n                                    Grid.Column=\"0\"\n                                    IsChecked=\"{Binding UseChinaServer, Mode=TwoWay}\"\n                                    VerticalOptions=\"Center\" />\n                                <Label\n                                    Grid.Row=\"5\"\n                                    Grid.Column=\"1\"\n                                    FontSize=\"Small\"\n                                    Text=\"Use China Server\"\n                                    VerticalOptions=\"Center\" />\n                                <CheckBox\n                                    Grid.Row=\"6\"\n                                    Grid.Column=\"0\"\n                                    IsChecked=\"{Binding HideAds, Mode=TwoWay}\"\n                                    VerticalOptions=\"Center\" />\n                                <Label\n                                    Grid.Row=\"6\"\n                                    Grid.Column=\"1\"\n                                    FontSize=\"Small\"\n                                    Text=\"{x:Static localization:AppSnippets.SettingsHideAds}\"\n                                    VerticalOptions=\"Center\" />\n\n                            </Grid>\n                            <Button\n                                Margin=\"0,10,0,10\"\n                                BackgroundColor=\"{StaticResource Primary}\"\n                                Command=\"{Binding ResetCommand}\"\n                                Text=\"{x:Static localization:AppSnippets.ResetToDefault}\"\n                                TextColor=\"White\" />\n                            <Button\n                                Margin=\"0,10,0,10\"\n                                BackgroundColor=\"{StaticResource Primary}\"\n                                Command=\"{Binding ResetTokensCommand}\"\n                                Text=\"Clear Garmin Tokens\"\n                                TextColor=\"White\" />\n                            \n                        </StackLayout>\n                    </Border>\n                </StackLayout>\n            </ScrollView>\n        </Grid>\n    </AbsoluteLayout>\n</ContentPage>"
  },
  {
    "path": "src/MiScaleExporter.MAUI/Views/SettingsPage.xaml.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Autofac;\nusing MiScaleExporter.MAUI;\nusing MiScaleExporter.MAUI.ViewModels;\n\nnamespace MiScaleExporter.MAUI.Views\n{\n    [XamlCompilation(XamlCompilationOptions.Compile)]\n    public partial class SettingPage : ContentPage\n    {\n        private ISettingsViewModel vm;\n        public SettingPage()\n        {\n            InitializeComponent();\n            using (var scope = App.Container.BeginLifetimeScope())\n            {\n                this.BindingContext = vm = scope.Resolve<ISettingsViewModel>();\n            }\n        }\n\n        private void SexRadioSetToMale(object sender, CheckedChangedEventArgs e)\n        {\n            if (e.Value)\n            {\n                vm.SexRadioSetToMale();\n            }\n        }\n        private void SexRadioSetToFemale(object sender, CheckedChangedEventArgs e)\n        {\n            if (e.Value)\n            {\n                vm.SexRadioSetToFemale();\n            }\n        }\n        private void ScaleTypeSetToBodyCompositionScale(object sender, CheckedChangedEventArgs e)\n        {\n            if (e.Value)\n            {\n                vm.ScaleTypeSetToBodyCompositionScale();\n            }\n\n        }\n        private void ScaleTypeSetToMiscale(object sender, CheckedChangedEventArgs e)\n        {\n            if (e.Value)\n            {\n                vm.ScaleTypeSetToMiscale();\n            }\n\n        }\n        private void ScaleTypeSetToS400(object sender, CheckedChangedEventArgs e)\n        {\n            if (e.Value)\n            {\n                vm.ScaleTypeSetToS400();\n            }\n\n        }\n\n        protected override async void OnAppearing()\n        {\n            base.OnAppearing();\n            await vm.LoadPreferencesAsync();\n        }\n    }\n}"
  }
]