├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── main.yml ├── .gitignore ├── .metadata ├── CONTRIBUTION_GUIDE.MD ├── LICENSE.txt ├── README.md ├── android ├── .gitignore ├── .project ├── .settings │ └── org.eclipse.buildship.core.prefs ├── app │ ├── .classpath │ ├── .project │ ├── .settings │ │ └── org.eclipse.buildship.core.prefs │ ├── build.gradle │ ├── google-services.json │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ │ └── app │ │ │ │ └── ceylon │ │ │ │ └── selftrackingapp │ │ │ │ ├── LocationDatabase.kt │ │ │ │ ├── MainActivity.kt │ │ │ │ ├── dao │ │ │ │ └── LocationDao.kt │ │ │ │ ├── model │ │ │ │ └── Location.kt │ │ │ │ └── service │ │ │ │ ├── LocationReceiver.kt │ │ │ │ └── LocationTrackingService.kt │ │ ├── res │ │ │ ├── drawable │ │ │ │ ├── govlogo128.png │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_stat_ic_notification.png │ │ │ │ ├── launch_background.xml │ │ │ │ └── launch_background_img.png │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_stat_ic_notification.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_stat_ic_notification.png │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_stat_ic_notification.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_stat_ic_notification.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_stat_ic_notification.png │ │ │ ├── mipmap │ │ │ │ └── ic_launcher.png │ │ │ └── values │ │ │ │ └── styles.xml │ │ └── web_hi_res_512.png │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── settings.gradle └── settings_aar.gradle ├── assets ├── data │ ├── constant_data.json │ └── countries.json ├── hospitals.json ├── images │ ├── add_ic_call_24px.svg │ ├── ambulance.svg │ ├── announcement_24px.svg │ ├── bg.png │ ├── casefinder_24px.svg │ ├── contactus_24px.svg │ ├── death.svg │ ├── home_24px.svg │ ├── hospital_sign_map.png │ ├── locateme_24px.svg │ ├── logo.png │ ├── medical_consultion.png │ ├── rehabilitation.svg │ ├── stay_safe.png │ ├── suspect.svg │ ├── suspected_icon.png │ ├── user_icon.png │ └── welcome_screen_bg.png └── lang │ ├── en.json │ ├── si.json │ └── ta.json ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Podfile ├── Podfile.lock ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-1024.png │ │ ├── Icon-20.png │ │ ├── Icon-20@2x.png │ │ ├── Icon-20@3x.png │ │ ├── Icon-29.png │ │ ├── Icon-29@2x.png │ │ ├── Icon-29@3x.png │ │ ├── Icon-40.png │ │ ├── Icon-40@2x.png │ │ ├── Icon-40@3x.png │ │ ├── Icon-60@2x.png │ │ ├── Icon-60@3x.png │ │ ├── Icon-76.png │ │ ├── Icon-76@2x.png │ │ ├── Icon-83.5@2x.png │ │ ├── Icon-App-1024x1024@1x.png │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ └── Icon-App-83.5x83.5@2x.png │ └── LaunchImage.imageset │ │ ├── Contents.json │ │ ├── LaunchImage.png │ │ ├── LaunchImage@2x.png │ │ ├── LaunchImage@3x.png │ │ └── README.md │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── GoogleService-Info.plist │ ├── Info.plist │ ├── Location.swift │ ├── LocationStore.swift │ ├── Runner-Bridging-Header.h │ └── Runner.entitlements ├── lib ├── app_localizations.dart ├── constants.dart ├── exceptions │ ├── data_fetch_exception.dart │ └── data_write_exception.dart ├── main.dart ├── models │ ├── contact_us_contact.dart │ ├── data_type.dart │ ├── fcm_message.dart │ ├── location.dart │ ├── message_type.dart │ ├── news_article.dart │ ├── registration.dart │ └── reported_case.dart ├── networking │ ├── api_client.dart │ ├── data_repository.dart │ └── db.dart ├── notifiers │ ├── registered_cases_model.dart │ └── stories_model.dart ├── page │ ├── ios_faq.dart │ └── screen │ │ ├── case_details_map_screen.dart │ │ ├── case_details_screen.dart │ │ ├── case_list_screen.dart │ │ ├── component │ │ └── news_component.dart │ │ ├── contact_us_screen.dart │ │ ├── dashboard_screen.dart │ │ ├── faq_screen.dart │ │ ├── news_detail_screen.dart │ │ ├── news_details_screen.dart │ │ ├── pharamacy_list_screen.dart │ │ ├── privacy_policy_screen.dart │ │ ├── qr_scan_screen.dart │ │ ├── qr_webview_screen.dart │ │ ├── root_screen.dart │ │ ├── selected_case_detail_screen.dart │ │ ├── user_register_screen.dart │ │ └── welcome_screen.dart ├── theme.dart ├── utils │ └── tracker_colors.dart └── widgets │ ├── animated_tracker_button.dart │ ├── case_item.dart │ ├── case_item_map_detail.dart │ ├── custom_text.dart │ └── language_select.dart ├── local.properties ├── pubspec.lock ├── pubspec.yaml ├── pull_request_template.md └── test └── widget_test.dart /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | tags: 7 | - v[0-9]+.[0-9]+.[0-9]+ 8 | - v[0-9]+.[0-9]+.[0-9]+-alpha* 9 | - v[0-9]+.[0-9]+.[0-9]+-beta* 10 | pull_request: 11 | branches: [ master ] 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | steps: 17 | 18 | - name: Set build mode 19 | run: | 20 | BUILD_MODE='debug' 21 | if [[ "${GITHUB_REF}" =~ ^refs\/tags\/v* ]]; then 22 | BUILD_MODE='release' 23 | elif [[ "${GITHUB_REF}" =~ ^refs\/heads\/master$ ]]; then 24 | BUILD_MODE='release' 25 | fi 26 | 27 | echo "Build mode: ${BUILD_MODE}" 28 | 29 | echo "::set-env name=BUILD_MODE::${BUILD_MODE}" 30 | 31 | - uses: actions/checkout@v2 32 | 33 | - uses: actions/setup-java@v1 34 | with: 35 | java-version: '8.x' 36 | 37 | - uses: subosito/flutter-action@v1 38 | with: 39 | flutter-version: '1.12.13+hotfix.9' 40 | 41 | - run: flutter pub get 42 | 43 | # - run: flutter analyze TODO: enable after fixing the issues in code 44 | 45 | - run: flutter test 46 | 47 | - name: Generate Android key store file 48 | if: ${{ env.BUILD_MODE == 'release' }} 49 | run: echo "${SIGNING_KEY}" | openssl base64 -d -out key.jks 50 | working-directory: ${{ github.workspace }}/android 51 | env: 52 | SIGNING_KEY: ${{ secrets.AndroidSigningKeyBase64 }} 53 | 54 | - name: Generate Android key.properties file 55 | if: ${{ env.BUILD_MODE == 'release' }} 56 | run: | 57 | echo "storePassword=${STORE_PASSWORD}" >> key.properties 58 | echo "keyPassword=${KEY_PASSWORD}" >> key.properties 59 | echo "keyAlias=key" >> key.properties 60 | echo "storeFile=../key.jks" >> key.properties 61 | working-directory: ${{ github.workspace }}/android 62 | env: 63 | STORE_PASSWORD: ${{ secrets.AndroidStorePassword }} 64 | KEY_PASSWORD: ${{ secrets.AndroidKeyPassword }} 65 | 66 | - name: Build Android packages 67 | run: flutter build apk "--${BUILD_MODE}" --target-platform android-arm,android-arm64,android-x64 --split-per-abi 68 | 69 | - name: Upload Android release artifacts 70 | if: ${{ env.BUILD_MODE == 'release' }} 71 | uses: actions/upload-artifact@v1 72 | with: 73 | name: android_release 74 | path: "build/app/outputs/apk/release" 75 | 76 | - name: Upload Android debug artifacts 77 | if: ${{ env.BUILD_MODE == 'debug' }} 78 | uses: actions/upload-artifact@v1 79 | with: 80 | name: android_debug 81 | path: "build/app/outputs/apk/debug" 82 | 83 | release: 84 | runs-on: ubuntu-latest 85 | needs: build 86 | if: success() && startsWith(github.ref, 'refs/tags/v') 87 | steps: 88 | - name: Generate version string 89 | run: echo "::set-env name=VERSION_STR::${GITHUB_REF##*/}" 90 | 91 | - uses: actions/download-artifact@v1 92 | with: 93 | name: android_release 94 | 95 | - uses: ncipollo/release-action@v1 96 | with: 97 | allowUpdates: true 98 | artifacts: "android_release/*.apk" 99 | name: Release ${{ env.VERSION_STR }} 100 | prerelease: ${{ contains(github.ref, '-alpha') || contains(github.ref, '-beta') }} 101 | tag: ${{ env.VERSION_STR }} 102 | token: ${{ secrets.GITHUB_TOKEN }} 103 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # Visual Studio Code related 13 | .vscode/ 14 | 15 | # IntelliJ related 16 | *.iml 17 | *.ipr 18 | *.iws 19 | .idea/ 20 | 21 | # The .vscode folder contains launch configuration and tasks you configure in 22 | # VS Code which you may wish to be included in version control, so this line 23 | # is commented out by default. 24 | #.vscode/ 25 | 26 | # Flutter/Dart/Pub related 27 | **/doc/api/ 28 | .dart_tool/ 29 | .flutter-plugins 30 | .flutter-plugins-dependencies 31 | .packages 32 | .pub-cache/ 33 | .pub/ 34 | /build/ 35 | 36 | # Web related 37 | lib/generated_plugin_registrant.dart 38 | 39 | # Exceptions to above rules. 40 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 41 | 42 | 43 | android/key.properties 44 | /android/app/release/ 45 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 27321ebbad34b0a3fafe99fac037102196d655ff 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /CONTRIBUTION_GUIDE.MD: -------------------------------------------------------------------------------- 1 | # Contributing to the COVID-19 Sri Lankan App 2 | 3 | Welcome and thank you for opting to contribute to our project! This is an Open Source Project developed by the Information and Communication Technology Agency of Sri Lanka (ICTA), with the extensive collaboration of the relevant stakeholders for the community under the patronage of the Government of Sri Lanka. 4 | 5 | All members in this project are expected to follow and adhere to our [Code of Conduct](https://docs.google.com/document/d/1as4zuQx0xisLtgNqYZYEtbGaBXFB6FxdJw_b2-e9YFM/edit#), please make sure to go through it. 6 | 7 | ## Table of Contents 8 | 9 | - [Repositories](https://docs.google.com/document/d/1GQD7_lD0HfW1v6q7xDGHgY8OoPiTKgQsQARQdJHDHKo/edit#heading=h.7z89lqh1pong) 10 | 11 | - [Getting Started](https://docs.google.com/document/d/1GQD7_lD0HfW1v6q7xDGHgY8OoPiTKgQsQARQdJHDHKo/edit#heading=h.o3ckrsq1dbyf) 12 | 13 | - [License](https://docs.google.com/document/d/1GQD7_lD0HfW1v6q7xDGHgY8OoPiTKgQsQARQdJHDHKo/edit#heading=h.o8toamvqv9jm) 14 | 15 | 16 | ## Repositories 17 | 18 | The following GitHub repositories are used: 19 | 20 | - [https://github.com/ayubowan/selft_tracking_app](https://github.com/ayubowan/selft_tracking_app) - Repository for the COVID-19 self-track app 21 | 22 | - [https://github.com/ICTASL/COVID-19](https://github.com/ICTASL/COVID-19) - Repository for the backend services needed for the COVID-19 self-tracking app 23 | 24 | 25 | 26 | All completed documentation related to the project can be found here: 27 | 28 | - [https://groups.google.com/forum/#!topic/govtechlk-corona/jlk4wDdbzT8](https://groups.google.com/forum/#!topic/govtechlk-corona/jlk4wDdbzT8) 29 | 30 | 31 | ## Getting Started 32 | 33 | - Download or clone the [repositories](https://docs.google.com/document/d/1GQD7_lD0HfW1v6q7xDGHgY8OoPiTKgQsQARQdJHDHKo/edit#heading=h.7z89lqh1pong). 34 | 35 | - Install [Flutter](https://flutter.dev/) to update the codebase and fix issues. 36 | 37 | - Read our [Code of Conduct](https://docs.google.com/document/d/1as4zuQx0xisLtgNqYZYEtbGaBXFB6FxdJw_b2-e9YFM/edit#) (if you have not done so already). 38 | 39 | - Read our [design documentation](https://docs.google.com/document/d/1sTe8a-uMpDEEFKnIDeP-SGTmHvTEdhJreiOfRGJpdN4/edit) to understand the scope of the project. 40 | 41 | - Join our public [Slack channel](https://join.slack.com/t/govtechlk/shared_invite/zt-cmk8k1z7-qUM~LqxNv1jcDLCwGGbzJA). 42 | 43 | - Report issues/bugs on our respective GitHub [repositories](https://docs.google.com/document/d/1GQD7_lD0HfW1v6q7xDGHgY8OoPiTKgQsQARQdJHDHKo/edit#heading=h.7z89lqh1pong), join the conversations on new features, comment on other issues, and send your pull requests. 44 | 45 | 46 | Tip: Not sure if you found a bug? Search existing issues in the corresponding repository on GitHub and raise it on our Slack channel. 47 | 48 | ## License 49 | 50 | - The source code is licensed under [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0). 51 | 52 | - Content is licensed under [CC By 4.0](https://creativecommons.org/licenses/by/4.0/). 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MyHealth Sri Lanka - Mobile App 2 | 3 | ![CI](https://github.com/ayubowan/selft_tracking_app/workflows/CI/badge.svg) 4 | 5 | ## Introduction 6 | 7 | Under the leadership of the Ministry of Health, we have already established a protocol for all incoming travelers to complete a declaration form, for that information to be entered into a disease surveillance platform and for that information to be shared with the public health monitoring system for active surveillance. 8 | 9 | As this system relies purely on self declaration, it leaves room for the possibility of travelers not being honest about their status and travel history as they would be attempting to avoid mandatory quarantine. 10 | 11 | We propose to integrate several data sources that are available to improve the overall architecture of the system to ensure use of reliable information and to provide an automated approach for every traveler to be recorded into the surveillance system. The proposed solution eliminates the use of a questionnaire to capture critical information such as flight information and only uses it for epidemiological surveillance questions. 12 | 13 | We further propose a Web based database of all Sri Lankans living outside of the country and a voluntary mobile app based location surveillance system to help manage contact surveillance. 14 | 15 | We believe this system can be finalized and deployed over the weekend and go live by Monday March 16th, 2020. 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | /key.properties 9 | -------------------------------------------------------------------------------- /android/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | android 4 | Project android created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.buildship.core.gradleprojectbuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.buildship.core.gradleprojectnature 16 | 17 | 18 | -------------------------------------------------------------------------------- /android/.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | arguments= 2 | auto.sync=false 3 | build.scans.enabled=false 4 | connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) 5 | connection.project.dir= 6 | eclipse.preferences.version=1 7 | gradle.user.home= 8 | java.home=/opt/jdk-11.0.2 9 | jvm.arguments= 10 | offline.mode=false 11 | override.workspace.settings=true 12 | show.console.view=true 13 | show.executions.view=true 14 | -------------------------------------------------------------------------------- /android/app/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /android/app/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | app 4 | Project app created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.buildship.core.gradleprojectbuilder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.buildship.core.gradleprojectnature 22 | 23 | 24 | -------------------------------------------------------------------------------- /android/app/.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | connection.project.dir=.. 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply plugin: 'com.google.gms.google-services' 27 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 28 | 29 | apply plugin: 'kotlin-kapt' 30 | apply plugin: 'kotlin-android-extensions' 31 | 32 | // Apply the Crashlytics Gradle plugin 33 | // apply plugin: 'com.google.firebase.crashlytics' 34 | 35 | def keystoreProperties = new Properties() 36 | def keystorePropertiesFile = rootProject.file('key.properties') 37 | if (keystorePropertiesFile.exists()) { 38 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) 39 | } 40 | 41 | android { 42 | compileSdkVersion 28 43 | 44 | sourceSets { 45 | main.java.srcDirs += 'src/main/kotlin' 46 | } 47 | 48 | lintOptions { 49 | disable 'InvalidPackage' 50 | } 51 | 52 | defaultConfig { 53 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 54 | applicationId "app.ceylon.selftrackingapp" 55 | minSdkVersion 24 56 | targetSdkVersion 29 57 | versionCode flutterVersionCode.toInteger() 58 | versionName flutterVersionName 59 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 60 | 61 | 62 | } 63 | 64 | signingConfigs { 65 | release { 66 | keyAlias keystoreProperties['keyAlias'] 67 | keyPassword keystoreProperties['keyPassword'] 68 | storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null 69 | storePassword keystoreProperties['storePassword'] 70 | } 71 | } 72 | buildTypes { 73 | release { 74 | signingConfig signingConfigs.release 75 | // signingConfig signingConfigs.debug 76 | } 77 | } 78 | } 79 | 80 | flutter { 81 | source '../..' 82 | } 83 | 84 | dependencies { 85 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 86 | testImplementation 'junit:junit:4.12' 87 | androidTestImplementation 'androidx.test:runner:1.1.1' 88 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' 89 | implementation 'com.google.firebase:firebase-analytics:17.2.2' 90 | implementation 'com.google.android.gms:play-services-location:17+' 91 | def room_version = "2.2.4" 92 | 93 | implementation "androidx.room:room-runtime:$room_version" 94 | kapt "androidx.room:room-compiler:$room_version" 95 | // For Kotlin use kapt instead of annotationProcessor 96 | 97 | // optional - Kotlin Extensions and Coroutines support for Room 98 | implementation "androidx.room:room-ktx:$room_version" 99 | 100 | // Add the Firebase SDK for Crashlytics. 101 | // implementation 'com.google.firebase:firebase-crashlytics:17+' 102 | // implementation 'com.google.firebase:firebase-messaging:20.1.6' 103 | 104 | 105 | 106 | } 107 | -------------------------------------------------------------------------------- /android/app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "1096700657713", 4 | "firebase_url": "https://covid-19-lk-dev.firebaseio.com", 5 | "project_id": "covid-19-lk-dev", 6 | "storage_bucket": "covid-19-lk-dev.appspot.com" 7 | }, 8 | "client": [ 9 | { 10 | "client_info": { 11 | "mobilesdk_app_id": "1:1096700657713:android:0a0df1ee8409b2909b5510", 12 | "android_client_info": { 13 | "package_name": "app.ceylon.selftrackingapp" 14 | } 15 | }, 16 | "oauth_client": [ 17 | { 18 | "client_id": "1096700657713-unbpqgi7v23616evj9kp288vtjqg5u2j.apps.googleusercontent.com", 19 | "client_type": 3 20 | } 21 | ], 22 | "api_key": [ 23 | { 24 | "current_key": "AIzaSyBz68l5B3gtQEHVE1crZ1m14pzkccVb0mo" 25 | } 26 | ], 27 | "services": { 28 | "appinvite_service": { 29 | "other_platform_oauth_client": [ 30 | { 31 | "client_id": "1096700657713-unbpqgi7v23616evj9kp288vtjqg5u2j.apps.googleusercontent.com", 32 | "client_type": 3 33 | } 34 | ] 35 | } 36 | } 37 | }, 38 | { 39 | "client_info": { 40 | "mobilesdk_app_id": "1:1096700657713:android:61dfc8a0080557ce9b5510", 41 | "android_client_info": { 42 | "package_name": "lk.gov.govtech.covid19" 43 | } 44 | }, 45 | "oauth_client": [ 46 | { 47 | "client_id": "1096700657713-unbpqgi7v23616evj9kp288vtjqg5u2j.apps.googleusercontent.com", 48 | "client_type": 3 49 | } 50 | ], 51 | "api_key": [ 52 | { 53 | "current_key": "AIzaSyBz68l5B3gtQEHVE1crZ1m14pzkccVb0mo" 54 | } 55 | ], 56 | "services": { 57 | "appinvite_service": { 58 | "other_platform_oauth_client": [ 59 | { 60 | "client_id": "1096700657713-unbpqgi7v23616evj9kp288vtjqg5u2j.apps.googleusercontent.com", 61 | "client_type": 3 62 | } 63 | ] 64 | } 65 | } 66 | } 67 | ], 68 | "configuration_version": "1" 69 | } -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/app/ceylon/selftrackingapp/LocationDatabase.kt: -------------------------------------------------------------------------------- 1 | package app.ceylon.selftrackingapp 2 | 3 | import android.content.Context 4 | import androidx.room.* 5 | import app.ceylon.selftrackingapp.dao.LocationDao 6 | import app.ceylon.selftrackingapp.model.LocationModel 7 | import java.util.* 8 | 9 | 10 | class Converters { 11 | @TypeConverter 12 | fun fromTimestamp(value: Long?): Date? { 13 | return value?.let { Date(it) } 14 | } 15 | 16 | @TypeConverter 17 | fun dateToTimestamp(date: Date?): Long? { 18 | return date?.time?.toLong() 19 | } 20 | } 21 | 22 | @Database(entities = [LocationModel::class], version = 1) 23 | @TypeConverters(Converters::class) 24 | abstract class LocationDatabase : RoomDatabase() { 25 | 26 | abstract fun locationDao(): LocationDao 27 | 28 | companion object { 29 | 30 | @Volatile private var INSTANCE: LocationDatabase? = null 31 | 32 | fun getInstance(context: Context): LocationDatabase = 33 | INSTANCE ?: synchronized(this) { 34 | INSTANCE ?: buildDatabase(context).also { INSTANCE = it } 35 | } 36 | 37 | private fun buildDatabase(context: Context) = 38 | Room.databaseBuilder(context.applicationContext, 39 | LocationDatabase::class.java, "covid_19_self_tracking_app") 40 | .build() 41 | } 42 | } -------------------------------------------------------------------------------- /android/app/src/main/kotlin/app/ceylon/selftrackingapp/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package app.ceylon.selftrackingapp 2 | 3 | import android.Manifest 4 | import android.content.Intent 5 | import android.content.pm.PackageManager 6 | import android.os.AsyncTask 7 | import android.os.Build 8 | import android.os.Bundle 9 | import android.os.Handler 10 | import androidx.annotation.NonNull 11 | import androidx.core.app.ActivityCompat 12 | import app.ceylon.selftrackingapp.dao.LocationDao 13 | import app.ceylon.selftrackingapp.service.LocationTrackingService 14 | import io.flutter.embedding.android.FlutterActivity 15 | import io.flutter.embedding.engine.FlutterEngine 16 | import io.flutter.plugin.common.MethodChannel 17 | import io.flutter.plugins.GeneratedPluginRegistrant 18 | import org.json.JSONObject 19 | 20 | 21 | class MainActivity : FlutterActivity() { 22 | companion object { 23 | const val CHANNEL = "location" 24 | const val LOCATION_UPDATE_REQUEST_CODE = 1554 25 | const val TAG = "MainActivity" 26 | } 27 | 28 | 29 | private lateinit var locationDao: LocationDao; 30 | var isLocationServiceRunning = false 31 | 32 | override fun onCreate(savedInstanceState: Bundle?) { 33 | super.onCreate(savedInstanceState) 34 | GeneratedPluginRegistrant.registerWith(this.flutterEngine!!); 35 | 36 | locationDao = LocationDatabase.getInstance(this).locationDao() 37 | 38 | 39 | 40 | 41 | MethodChannel(flutterEngine!!.dartExecutor, CHANNEL).setMethodCallHandler { call, result -> 42 | 43 | 44 | if (call.method == "getLocation") { 45 | 46 | val handler = Handler() 47 | AsyncTask.execute { 48 | val allLocations = locationDao.getAll(); 49 | var message = ""; 50 | val locaitons = ArrayList(allLocations.size) 51 | for (location in allLocations) { 52 | val jsonLocation = JSONObject() 53 | jsonLocation.put("longitude", location.lng) 54 | jsonLocation.put("latitude", location.lat) 55 | jsonLocation.put("recordedAt", location.date?.time) 56 | jsonLocation.put("title", location.dateString) 57 | locaitons.add(jsonLocation.toString(10)) 58 | } 59 | 60 | handler.post { 61 | result.success(locaitons); 62 | } 63 | } 64 | 65 | } else if (call.method == "requestLocationPermission") { 66 | val permissionAccessCoarseLocationApproved = ActivityCompat 67 | .checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == 68 | PackageManager.PERMISSION_GRANTED 69 | 70 | if (permissionAccessCoarseLocationApproved) { 71 | result.success("PERMISSION_GRANTED"); 72 | } else { 73 | // Make a request for foreground-only location access. 74 | ActivityCompat.requestPermissions(this, 75 | arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION), 76 | LOCATION_UPDATE_REQUEST_CODE 77 | ) 78 | result.success("PERMISSION_GRANTED"); 79 | } 80 | } else if (call.method == "openLocationService") { 81 | if (!isLocationServiceRunning) 82 | Intent(this, LocationTrackingService::class.java).also { intent -> 83 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 84 | startForegroundService(intent) 85 | } else { 86 | startService(intent); 87 | } 88 | isLocationServiceRunning = true 89 | } 90 | result.success("LOCATION_SERVICE_RUNNING"); 91 | } 92 | } 93 | 94 | } 95 | 96 | 97 | private fun getLocationUpdate(): String? { 98 | val location = null//locationService?.getCurrentLocation(); 99 | val locationResult: String? = ""//"${location?.longitude},${location?.latitude}" 100 | return locationResult 101 | } 102 | 103 | override fun onDestroy() { 104 | flutterEngine?.platformViewsController?.onFlutterViewDestroyed() 105 | super.onDestroy() 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/app/ceylon/selftrackingapp/dao/LocationDao.kt: -------------------------------------------------------------------------------- 1 | package app.ceylon.selftrackingapp.dao 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Insert 5 | import androidx.room.Query 6 | import app.ceylon.selftrackingapp.model.LocationModel 7 | import java.util.* 8 | 9 | @Dao 10 | interface LocationDao { 11 | @Query("SELECT * FROM locationmodel") 12 | fun getAll(): List 13 | 14 | @Query("SELECT * FROM locationmodel ORDER BY date DESC LIMIT 1") 15 | fun getLastLocation():LocationModel 16 | 17 | @Query("SELECT * FROM locationmodel WHERE date BETWEEN :startDate and :endDate") 18 | fun getAllByDateRange(startDate: Date, endDate: Date): List 19 | 20 | @Insert 21 | fun insert(vararg locations: LocationModel) 22 | } -------------------------------------------------------------------------------- /android/app/src/main/kotlin/app/ceylon/selftrackingapp/model/Location.kt: -------------------------------------------------------------------------------- 1 | package app.ceylon.selftrackingapp.model 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | import androidx.room.PrimaryKey 6 | import java.util.* 7 | 8 | 9 | @Entity 10 | data class LocationModel( 11 | @ColumnInfo(name = "lat") val lat: Double?, 12 | @ColumnInfo(name = "lng") val lng: Double?, 13 | @ColumnInfo(name = "date") val date: Date?, 14 | @ColumnInfo(name = "date_string") val dateString: String? 15 | ) { 16 | 17 | @PrimaryKey(autoGenerate = true) 18 | var uid: Int = 0 19 | } -------------------------------------------------------------------------------- /android/app/src/main/kotlin/app/ceylon/selftrackingapp/service/LocationReceiver.kt: -------------------------------------------------------------------------------- 1 | package app.ceylon.selftrackingapp.service 2 | 3 | import android.content.BroadcastReceiver 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.os.Build 7 | import android.util.Log 8 | 9 | const val TAG = "LocationReceiver" 10 | 11 | class LocationReceiver : BroadcastReceiver() { 12 | override fun onReceive(context: Context, intent: Intent) { 13 | val background = Intent(context, LocationTrackingService::class.java) 14 | Log.i(TAG, "Working on background"); 15 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 16 | context.startForegroundService(intent) 17 | } else { 18 | context.startService(intent); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /android/app/src/main/kotlin/app/ceylon/selftrackingapp/service/LocationTrackingService.kt: -------------------------------------------------------------------------------- 1 | package app.ceylon.selftrackingapp.service 2 | 3 | import android.app.* 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.location.Location 7 | import android.os.* 8 | import android.util.Log 9 | import app.ceylon.selftrackingapp.LocationDatabase 10 | import app.ceylon.selftrackingapp.MainActivity 11 | import app.ceylon.selftrackingapp.dao.LocationDao 12 | import app.ceylon.selftrackingapp.model.LocationModel 13 | import com.google.android.gms.location.* 14 | import java.util.* 15 | 16 | 17 | class LocationTrackingService : Service() { 18 | 19 | private val binder: IBinder = AppServiceBinder() 20 | private val CHANNEL_ID = "11111" 21 | private val CHANNEL_NAME = "ForegroundServiceChannel" 22 | 23 | inner class AppServiceBinder : Binder() { 24 | val service: LocationTrackingService 25 | get() = this@LocationTrackingService 26 | } 27 | 28 | override fun onBind(intent: Intent?): IBinder? { 29 | return binder 30 | } 31 | 32 | private lateinit var locationDao: LocationDao; 33 | private val handler = Handler() 34 | 35 | override fun onCreate() { 36 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 37 | val channel = NotificationChannel(CHANNEL_ID, CHANNEL_NAME, 38 | NotificationManager.IMPORTANCE_HIGH) 39 | val manager: NotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager 40 | manager.createNotificationChannel(channel) 41 | 42 | 43 | val pendingIntent: PendingIntent = PendingIntent.getActivity( 44 | this, 45 | 0, 46 | Intent(this,MainActivity::class.java), 47 | PendingIntent.FLAG_UPDATE_CURRENT) 48 | 49 | 50 | val notification = Notification.Builder(applicationContext, CHANNEL_ID) 51 | .setContentIntent(pendingIntent) 52 | .build() 53 | startForeground(1, notification) 54 | } else { 55 | 56 | } 57 | 58 | 59 | locationDao = LocationDatabase.getInstance(this).locationDao() 60 | startLocationUpdates(); 61 | } 62 | 63 | private var mLocationRequest: LocationRequest? = null 64 | 65 | private val UPDATE_INTERVAL = 20 * 60 * 1 * 1000 /* 10 secs */.toLong() 66 | private val FASTEST_INTERVAL: Long = 2 * 60 * 1 * 1000 /* 2 sec */ 67 | 68 | 69 | // Trigger new location updates at interval 70 | protected fun startLocationUpdates() { // Create the location request to start receiving updates 71 | mLocationRequest = LocationRequest() 72 | mLocationRequest!!.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY 73 | mLocationRequest!!.smallestDisplacement = 10.0f 74 | mLocationRequest!!.interval = UPDATE_INTERVAL 75 | mLocationRequest!!.fastestInterval = FASTEST_INTERVAL 76 | // Create LocationSettingsRequest object using location request 77 | val builder = LocationSettingsRequest.Builder() 78 | builder.addLocationRequest(mLocationRequest!!) 79 | val locationSettingsRequest = builder.build() 80 | // Check whether location settings are satisfied 81 | // https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient 82 | val settingsClient = LocationServices.getSettingsClient(this) 83 | settingsClient.checkLocationSettings(locationSettingsRequest) 84 | // new Google API SDK v11 uses getFusedLocationProviderClient(this) 85 | LocationServices.getFusedLocationProviderClient(this).requestLocationUpdates(mLocationRequest, object : LocationCallback() { 86 | override fun onLocationResult(locationResult: LocationResult) { // do work here 87 | onLocationChanged(locationResult.lastLocation) 88 | } 89 | }, 90 | Looper.myLooper()) 91 | } 92 | 93 | fun onLocationChanged(location: Location) { // New location has now been determined 94 | 95 | val dateTime = Date(location.time) 96 | var locationModel = LocationModel( 97 | date = dateTime, 98 | dateString = dateTime.toString(), 99 | lat = location.latitude, 100 | lng = location.longitude); 101 | 102 | AsyncTask.execute { 103 | val lastLocationModel = locationDao.getLastLocation() 104 | 105 | if (lastLocationModel != null) { 106 | 107 | val lastLocation = Location("Last Location"); 108 | lastLocation.latitude = lastLocation.latitude 109 | lastLocation.longitude = lastLocation.longitude 110 | 111 | val distanceTo = location.distanceTo(lastLocation); 112 | 113 | if (distanceTo > 50) { 114 | locationDao.insert(locationModel) 115 | } 116 | } else { 117 | locationDao.insert(locationModel) 118 | } 119 | 120 | 121 | 122 | handler.post { 123 | // Toast.makeText(this, "Location Updated ${locationModel.lng},${locationModel.lat},${locationModel.date?.time}", Toast.LENGTH_LONG).show() 124 | } 125 | } 126 | Log.i(MainActivity.TAG, "Location store ${locationModel.lat},${locationModel.lng}") 127 | // You can now create a LatLng Object for use with maps 128 | 129 | } 130 | } -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/govlogo128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/android/app/src/main/res/drawable/govlogo128.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/android/app/src/main/res/drawable/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/ic_stat_ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/android/app/src/main/res/drawable/ic_stat_ic_notification.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background_img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/android/app/src/main/res/drawable/launch_background_img.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_stat_ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/android/app/src/main/res/mipmap-hdpi/ic_stat_ic_notification.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_stat_ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/android/app/src/main/res/mipmap-mdpi/ic_stat_ic_notification.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_stat_ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/android/app/src/main/res/mipmap-xhdpi/ic_stat_ic_notification.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_stat_ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/android/app/src/main/res/mipmap-xxhdpi/ic_stat_ic_notification.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_stat_ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/android/app/src/main/res/mipmap-xxxhdpi/ic_stat_ic_notification.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/android/app/src/main/res/mipmap/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /android/app/src/main/web_hi_res_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/android/app/src/main/web_hi_res_512.png -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | ext.play_version = '20+' 4 | repositories { 5 | google() 6 | jcenter() 7 | } 8 | 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.6.3' 11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 12 | classpath 'com.google.gms:google-services:4.3.3' 13 | // Add the Crashlytics Gradle plugin. 14 | classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0-beta02' 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | google() 21 | jcenter() 22 | } 23 | } 24 | 25 | rootProject.buildDir = '../build' 26 | subprojects { 27 | project.buildDir = "${rootProject.buildDir}/${project.name}" 28 | } 29 | subprojects { 30 | project.evaluationDependsOn(':app') 31 | } 32 | 33 | task clean(type: Delete) { 34 | delete rootProject.buildDir 35 | } 36 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon May 18 09:05:24 IST 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip 7 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /android/settings_aar.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /assets/data/constant_data.json: -------------------------------------------------------------------------------- 1 | { 2 | "contact_us_contacts": [ 3 | { 4 | "id": 1, 5 | "title": "1990", 6 | "sub_title": "medical_emergency", 7 | "link": "tel:1990", 8 | "address": "", 9 | "title_translate": false, 10 | "subtitle_translate": true 11 | }, 12 | { 13 | "id": 3, 14 | "sub_title": "medical_consultation_service_foc", 15 | "title": "medical_consultation_service_title", 16 | "address": "", 17 | "title_translate": true, 18 | "subtitle_translate": true, 19 | "sub": [ 20 | { 21 | "id": 1, 22 | "title": "oDoc", 23 | "link": "https://play.google.com/store/apps/details?id=com.developer.odoc,https://apps.apple.com/lk/app/odoc/id1263423673", 24 | "address": "", 25 | "title_translate": false, 26 | "subtitle_translate": true 27 | }, 28 | { 29 | "id": 2, 30 | "title": "MyDoctor", 31 | "link": "https://play.google.com/store/apps/details?id=com.app.mydoctor,https://apps.apple.com/us/app/mydoctor-customer-app/id1242769715", 32 | "address": "", 33 | "title_translate": false, 34 | "subtitle_translate": true 35 | } 36 | ] 37 | }, 38 | { 39 | "id": 4, 40 | "title": "1999", 41 | "sub_title": "health_information", 42 | "link": "tel:1999", 43 | "address": "", 44 | "title_translate": false, 45 | "subtitle_translate": true 46 | }, 47 | { 48 | "id": 5, 49 | "title": "117", 50 | "sub_title": "covid_19_information", 51 | "link": "tel:117", 52 | "address": "", 53 | "title_translate": false, 54 | "subtitle_translate": true 55 | } 56 | ], 57 | "list": [ 58 | { 59 | "id": 2, 60 | "title": "pharmacy_list", 61 | "sub_title": "", 62 | "link": "https://pharmacy.health.gov.lk/", 63 | "address": "", 64 | "title_translate": true, 65 | "subtitle_translate": false 66 | } 67 | ], 68 | "privacy_policy": "We do not send locations to DHIS system unless you choose to share.All news and alerts comes from verified source" 69 | } 70 | 71 | 72 | -------------------------------------------------------------------------------- /assets/hospitals.json: -------------------------------------------------------------------------------- 1 | { 2 | "hospitals": [ 3 | { 4 | "name": "NHSL", 5 | "lon": 6.917705000000001, 6 | "lat": 79.866385, 7 | "id": 1, 8 | "hsId": "LCB0000018" 9 | }, 10 | { 11 | "name": "NH Kandy", 12 | "lon": 7.287566, 13 | "lat": 80.631834, 14 | "id": 2, 15 | "hsId": "LKY0001008" 16 | }, 17 | { 18 | "name": "LRH", 19 | "lon": 6.918231, 20 | "lat": 79.876479, 21 | "id": 3, 22 | "hsId": "LCB0000216" 23 | }, 24 | { 25 | "name": "CSHW", 26 | "lon": 6.910289, 27 | "lat": 79.884778, 28 | "id": 4, 29 | "hsId": "LCB0000166" 30 | }, 31 | { 32 | "name": "IDH", 33 | "lon": 6.922314999999999, 34 | "lat": 79.916981, 35 | "id": 5, 36 | "hsId": "LCB0000117" 37 | }, 38 | { 39 | "name": "CNTH Ragama", 40 | "lon": 7.028176147000001, 41 | "lat": 79.92352948, 42 | "id": 6, 43 | "hsId": "LGP0000703" 44 | }, 45 | { 46 | "name": "TH Anuradhapura", 47 | "lon": 8.324937955, 48 | "lat": 80.41297135, 49 | "id": 7, 50 | "hsId": "LAN0000034" 51 | }, 52 | { 53 | "name": "T H Batticaloa", 54 | "lon": 7.708293551000001, 55 | "lat": 81.69119854, 56 | "id": 8, 57 | "hsId": "LBC0000075" 58 | }, 59 | { 60 | "name": "TH Rathnapura", 61 | "lon": 6.6866923, 62 | "lat": 80.3925328, 63 | "id": 9, 64 | "hsId": "" 65 | }, 66 | { 67 | "name": "TH Karapitiya", 68 | "lon": 6.066744, 69 | "lat": 80.226084, 70 | "id": 10, 71 | "hsId": "LGL0000620" 72 | }, 73 | { 74 | "name": "TH Kurunegala", 75 | "lon": 7.4794793539999995, 76 | "lat": 80.35857174, 77 | "id": 11, 78 | "hsId": "" 79 | }, 80 | { 81 | "name": "TH Jaffna", 82 | "lon": 9.665931, 83 | "lat": 80.014377, 84 | "id": 12, 85 | "hsId": "LJF0000786" 86 | }, 87 | { 88 | "name": "PGH Badulla", 89 | "lon": 6.990918, 90 | "lat": 81.05161899999999, 91 | "id": 13, 92 | "hsId": "" 93 | }, 94 | { 95 | "name": "BH Mulleriyawa", 96 | "lon": 6.92605, 97 | "lat": 79.943753, 98 | "id": 14, 99 | "hsId": "LCB0000125" 100 | }, 101 | { 102 | "name": "DGH Hambantota", 103 | "lon": 6.126806998999999, 104 | "lat": 81.12261318, 105 | "id": 15, 106 | "hsId": "" 107 | }, 108 | { 109 | "name": "DGH Negombo", 110 | "lon": 7.21235, 111 | "lat": 79.84828167, 112 | "id": 16, 113 | "hsId": "" 114 | }, 115 | { 116 | "name": "DGH Gampaha", 117 | "lon": 7.091504700000001, 118 | "lat": 79.9999527, 119 | "id": 17, 120 | "hsId": "" 121 | }, 122 | { 123 | "name": "BH Chilaw", 124 | "lon": 7.57220396, 125 | "lat": 79.79742705, 126 | "id": 18, 127 | "hsId": "" 128 | }, 129 | { 130 | "name": "DGH Polonnaruwa", 131 | "lon": 7.9425338000000005, 132 | "lat": 81.0092566, 133 | "id": 19, 134 | "hsId": "" 135 | }, 136 | { 137 | "name": "DGH Vavuniya", 138 | "lon": 8.760660000000001, 139 | "lat": 80.49991, 140 | "id": 20, 141 | "hsId": "" 142 | }, 143 | { 144 | "name": "CSTH Kalubowila", 145 | "lon": 6.866891000000001, 146 | "lat": 79.876861, 147 | "id": 21, 148 | "hsId": "LCB0000174" 149 | }, 150 | { 151 | "name": "BH Marawila", 152 | "lon": 7.393453, 153 | "lat": 79.8321376, 154 | "id": 22, 155 | "hsId": "" 156 | }, 157 | { 158 | "name": "DGH Monaragala", 159 | "lon": 6.8918800000000005, 160 | "lat": 81.34253000000001, 161 | "id": 23, 162 | "hsId": "" 163 | }, 164 | { 165 | "name": "DGH Kalutara", 166 | "lon": 6.563859, 167 | "lat": 79.984344, 168 | "id": 24, 169 | "hsId": "" 170 | }, 171 | { 172 | "name": "DGH Matara", 173 | "lon": 5.964130394, 174 | "lat": 80.49414381, 175 | "id": 25, 176 | "hsId": "" 177 | }, 178 | { 179 | "name": "KDU", 180 | "lon": 6.8260902, 181 | "lat": 79.9043642, 182 | "id": 26, 183 | "hsId": "" 184 | }, 185 | { 186 | "name": "BH Minuwangoda", 187 | "lon": 7.17237, 188 | "lat": 79.95714833, 189 | "id": 27, 190 | "hsId": "PGP0005686" 191 | }, 192 | { 193 | "name": "BH Homagama", 194 | "lon": 6.847334768, 195 | "lat": 79.99156892, 196 | "id": 28, 197 | "hsId": "PCB0004002" 198 | }, 199 | { 200 | "name": "BH Welikanda", 201 | "lon": 7.947781667, 202 | "lat": 81.245785, 203 | "id": 29, 204 | "hsId": "" 205 | }, 206 | { 207 | "name": "Nevile Fernando", 208 | "lon": 6.9244512, 209 | "lat": 79.96039990000001, 210 | "id": 30, 211 | "hsId": "" 212 | } 213 | ] 214 | } -------------------------------------------------------------------------------- /assets/images/add_ic_call_24px.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/ambulance.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/announcement_24px.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/assets/images/bg.png -------------------------------------------------------------------------------- /assets/images/casefinder_24px.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/contactus_24px.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/death.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /assets/images/home_24px.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/hospital_sign_map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/assets/images/hospital_sign_map.png -------------------------------------------------------------------------------- /assets/images/locateme_24px.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/assets/images/logo.png -------------------------------------------------------------------------------- /assets/images/medical_consultion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/assets/images/medical_consultion.png -------------------------------------------------------------------------------- /assets/images/rehabilitation.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /assets/images/stay_safe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/assets/images/stay_safe.png -------------------------------------------------------------------------------- /assets/images/suspect.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/suspected_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/assets/images/suspected_icon.png -------------------------------------------------------------------------------- /assets/images/user_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/assets/images/user_icon.png -------------------------------------------------------------------------------- /assets/images/welcome_screen_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/assets/images/welcome_screen_bg.png -------------------------------------------------------------------------------- /assets/lang/si.json: -------------------------------------------------------------------------------- 1 | { 2 | "language_screen_choose": "ඔබේ මනාපය තෝරන්න", 3 | "language_screen_choose_sub": "කරුණාකර පහත භාෂාවක් තෝරන්න", 4 | "welcome_screen_language_button_text": "සිංහල", 5 | "welcome_screen_button_text": "ඊළඟ", 6 | "dashboard_welcome_title": "ආයුබෝවන්", 7 | "dashboard_latest_figures_title": "දත්ත", 8 | "dashboard_confirmed_card_text": "තහවුරු කළ", 9 | "dashboard_suspected_card_text": "සැක සහිත", 10 | "dashboard_recovered_card_text": "සුවය ලද", 11 | "dashboard_deaths_card_text": "මියගිය", 12 | "dashboard_last_updated_text": "යාවත්කාලීන වූ වේලාව : ", 13 | "dashboard_news_text": "පුවත්", 14 | "dashboard_home_tab_text": "නිවැසුම", 15 | "dashboard_location_tab_text": "පිහිටුම", 16 | "dashboard_safe_track_tab_text": "ස්ථාන", 17 | "dashboard_case_list_tab_text": "සිදුවීම්", 18 | "dashboard_contact_tab_text": "ටෙලි වෛද්\u200Dය සේවා", 19 | "dashboard_register_tab_text": "ලියාපදිංචි", 20 | "user_register_bar_title_text": "ලියාපදිංචි වන්න", 21 | "user_register_screen_title": "සබැඳි සිද්ධියක් සදහා ලියාපදිංචි වන්න", 22 | "user_register_screen_subtitle": "රෝගය තහවුරු වූ අයෙක් අසළ සිටියේද ?", 23 | "user_register_screen_name": "නම", 24 | "user_register_screen_age": "වයස", 25 | "user_register_screen_email": "විද්යුත් තැපෑල", 26 | "user_register_screen_phone": "ජංගම දූරකථන අංකය", 27 | "user_register_screen_invalid_name": "වලංගු නමක් ඇතුළත් කරන්න", 28 | "user_register_screen_invalid_age": "නිවැරදි වයස ඇතුළත් කරන්න", 29 | "user_register_screen_invalid_number": "වලංගු අංකයක් ඇතුළත් කරන්න", 30 | "user_register_screen_invalid_email": "වලංගු ලිපිනයක් ඇතුලත් කරන්න", 31 | "user_register_screen_selected_text": "එකතුකළ සිද්ධි", 32 | "user_register_screen_add_text": "+ සිද්ධි එක්කරන්න", 33 | "user_registration_screen_no_text": "සිද්ධි තෝරා නොමැත", 34 | "case_list_screen_search": "ස්ථානය අනුව සොයන්න", 35 | "case_list_screen_remove_text": "ඉවත්කරන්න", 36 | "cse_list_screen_see-text": "එකතුකළ", 37 | "############": "####################################", 38 | "welcome_screen_subtitle": "Together we can defeat COVID-19", 39 | "dashboard_screen_title": "Dashboard", 40 | "dashboard_screen_welcome_message": "Dashboard", 41 | "dashboard_screen_data_received": "Data Received", 42 | "dashboard_screen_news_button": "Select News", 43 | "dashboard_screen_case_list_button": "Case List", 44 | "dashboard_screen_case_details_button": "Case Details", 45 | "dashboard_screen_contact_us_button": "Contact Us", 46 | "dashboard_screen_privacy_policy_button": "Privacy Policy", 47 | "contact_us_screen_contact_us_title": "Get in touch.", 48 | "dashboard_screen_ok_button": "OK", 49 | "news_detail_page_title": "Register", 50 | "popmenu_language": "භාෂාව", 51 | "popmenu_faq": "නිතර අසන පැන", 52 | "popmenu_ios_faq": "නිතර අසන පැන", 53 | "popmenu_privpolicy": "රහස්\u200Dයතා ප්‍රතිපත්තිය", 54 | "faq": { 55 | "\"කොරෝනා වෛරසය යනු කුමක්ද?\"": "\"කොරෝනා වෛරස් යනු සතුන් හෝ මිනිසුන් තුළ රෝගාබාධ ඇති කළ හැකි විශාල වෛරස් පවුලකි. කොරෝනා පවුලට අයත් වෛරස කිහිපයක් මිනිසුන් තුළ, සාමාන්‍ය සෙම්ප්‍රතිශ්‍යාවේ සිට මැදපෙරදිග ශ්වසන සින්ඩ්‍රෝමය (MERS) සහ දරුණු උග්‍ර ශ්වසන සින්ඩ්‍රෝමය (SARS) වැනි දරුණු රෝග දක්වා ශ්වසන ආසාදන ඇති කරන බව දන්නා කරුණකි. මෑතකදී සොයාගත් කොරෝනා වයිරස් මගින් COVID-19කොරෝනා වයිරස් රෝගයට හේතු වේ.\"", 56 | "\"COVID-19 රෝගය පැතිරෙන්නේ කෙසේද?\"": "\"මිනිසුන්ට වෛරසය ඇති අයගෙන් COVID-19 බෝවිය හැකිය. COVID-19 සහිත පුද්ගලයෙකු කැස්ස හෝ හුස්ම ගන්නා විට නාසයෙන් හෝ මුඛයෙන් පිටවන බිඳිති හරහා මෙම රෝගය පුද්ගලයාගෙන් පුද්ගලයාට පැතිර යා හැකිය. මෙම බිඳිති පුද්ගලයා වටා ඇති වස්තූන් හා පෘෂ්ඨයන් මත තැන්පත්වේ. අනෙකුත් අයට COVID-19 වෛරසය ශරීර ගත වන්නේ මෙම වස්තූන් හෝ පෘෂ්ඨයන් ස්පර්ශ කිරීමෙන් පසුව ඔවුන්ගේ ඇස්, නාසය හෝ මුඛය ස්පර්ශ කිරීමෙනි. COVID-19 සහිත පුද්ගලයෙකුගේ ගෙන් පිටවන බිඳිති ආශ්වාස කළහොත් මිනිසුන්ට COVID-19 බෝවිය හැක. අසනීපයෙන් පෙළෙන පුද්ගලයෙකුගෙන් මීටර 1 ක් (අඩි 3) වඩා දුරින් සිටීම වැදගත් වන්නේ මේ නිසා ය. COVID-19 ව්‍යාප්ත වී ඇති ආකාරය පිළිබඳ අඛණ්ඩ පර්යේෂණ ලෝක සෞඛ්‍ය සංවිධානය තක්සේරු කරමින් සිටින අතර යාවත්කාලීන කරන ලද සොයාගැනීම් දිගටම බෙදා ගනු ඇත.\"", 57 | "\"COVID-19 හි රෝග ලක්ෂණ:\"": "\"මෙහි වඩාත් පොදු රෝග ලක්ෂණ වන්නේ, උණ, විඩාව, සහ වියලි කැස්ස වේ. සමහර රෝගීන්ට ඇඟ පත වේදනා, නාසය සිරවීම, සොටු දියර ගැලීම, උගුරේ අමාරුව හෝ පාචනය ඇති විය හැක. මෙම ලක්ෂණ සුළුවෙන් පටන් ගෙන, ක්‍රම ක්‍රමයෙන් මතුවිය හැක.සමහර පුද්ගලයන් අසාදිත වුවත් කිසිදු රෝග ලක්ෂණයක් නොපෙන්වන අතර, අසනීප බවක් නොදැනේ. බොහෝ අය (80%ක් පමණ) විශේෂ අවශ්‍ය නොවී, රෝගයෙන් සුවය ලබති. COVID-19 අසාදිත සෑම පුද්ගලයන් 6 දෙනෙකුගෙන් 1 අයකුම බරපතල ලෙස රෝගාතුරවී හුස්ම ගැනීමේ අපහසුතාවයක් ඇතිවේ. වැඩිහිටි පුද්ගලයින් සහ අධි රුධිර පීඩනය, හදවත් රෝග හෝ දියවැඩියාව වැනි නිදන්ගත රෝග ඇති අයට සංකුලතා ඇතිවීමේ ඉඩ කඩ ඇත. උණ, කැස්ස, සහ හුස්ම ගැනීමේ අපහසුතා ඇති අය වෛද්‍ය ප්‍රතිකාර ලබා ගත යුතුවේ.\"", 58 | "\"COVID-19 වෛරසය වාතය හරහා බෝවිය හැකිද?\"": "\"මේ දක්වා අධ්‍යන වලින් පෙනී යන්නේ COVID-19 වෛරසය ප්‍රධාන වශයෙන් සම්ප්‍රේෂණය වන්නේ වාතය හරහා නොව කැස්සකදී හෝ කිවිසුමකදී පිටවන බිඳිති බවයි.\"", 59 | "\"COVID-19 රෝගය, රෝග ලක්ෂණ නොපෙන්වන පුද්ගලයකු මගින් බෝවිය හැකිද ?\"": "\"රෝගය පැතිරෙන ප්‍රධාන ක්‍රමය වන්නේ පුද්ගලයකු කහින විට පිටවන බිඳිති මගිනි.එබැවින් කිසිදු රෝග ලක්ෂණයක් නොපෙන්වන රෝගියකු මගින් COVID-19 රෝගය බෝවීමේ අවදානම ඉතා අඩුය.එසේ වුවත් COVID-19 රෝගීන්ට බොහෝවිට පවතින්නේ සුළු රෝග ලක්ෂණ පමණි. මේ තත්ත්වය රෝගයේ මුල් අවධියේදී දැකිය හැක. එහෙත් ඇතැම් විට මෙම තත්ත්වය වෙනස් විය හැක. ලෝක සෞඛ්‍ය සංවිධානය, COVID-19 රෝගය සම්ප්‍රේෂණය වන කාල පරිච්චේදය පිළිබඳ තක්සේරු කරමින් සිටින අතර යාවත්කාලීන කරන ලද සොයාගැනීම් පිළිබඳව අප ඔබව දැනුවත් කරන්නෙමු.\"", 60 | "\"අසාදිත පුද්ගලයකුගේ මලපහ මගින්, COVID-19 රෝගය බෝවිය හැකිද?\"": "\"අසාදිත පුද්ගලයකුගේ මළ මුත්‍ර මගින් COVID-19 බෝවීමේ අවධානම අඩුය. එහෙත් ඇතැම් විට මෙම තත්ත්වය වෙනස් විය හැක. ලෝක සෞඛ්‍ය සංවිධානය, COVID-19 රෝගය සම්ප්‍රේෂණය වන කාල පරිච්චේදය පිළිබඳ තක්සේරු කරමින් සිටින අතර යාවත්කාලීන කරන ලද සොයාගැනීම් පිළිබඳව අප ඔබව දැනුවත් කරන්නෙමු.\"" 61 | }, 62 | "home_address": "ලිපිනය", 63 | "sri_lankan_citizan": "ඔබ ශ්\u200Dරී ලාංකික පුරවැසියෙක්ද?", 64 | "radio_yes": "ඔව්", 65 | "radio_no": "නැත", 66 | "nic_no": "ජාතික හැඳුනුම්පත් අංකය", 67 | "select_a_gender": "ස්ත්\u200Dරී / පුරුෂ භාවය", 68 | "menu_item_male": "පුරුෂ", 69 | "menu_item_female": "ස්ත්\u200Dරී", 70 | "menu_item_other": "වෙනත්", 71 | "register": "ලියාපදිංචි වන්න", 72 | "passport_number": " විදේශ ගමන් බලපත්\u200Dර අංක\u200Bය", 73 | "tos_decline_button": "එකඟ නොවේ", 74 | "tos_dialog_title": "භාවිතය සඳහා කොන්දේසි", 75 | "tos_accept_button": "එකඟයි", 76 | "tos_title": "MyHealth Sri Lanka යෙදුම භාවිතයේදී,", 77 | "tos_line_one": "MyHealth Sri Lanka යෙදුම මා සිටින ස්ථානය පිළිබඳ තොරතුරු මගේ ජංගම දුරකථනය/උපාංගය තුළ ආරක්ෂිතව තැන්පත් කරනු ඇති අතර, තැන්පත් කළ ස්ථානීය තොරතුරු මගේ නිසි පූර්ව කැමැත්තකින් තොරව උපාංගයෙන් පිටතට මාරු නොකෙරේ.", 78 | "tos_line_two": "MyHealth Sri Lanka යෙදුම ශ්\u200Dරී ලංකා සෞඛ්\u200Dය අමාත්\u200Dයාංශය සතු සහ කළමනාකරණය කරන ලද මේඝයෙහි (cloud) මගේ ලියාපදිංචි පෞද්ගලික තොරතුරු ආරක්ෂිතව ගබඩා කරනු ඇත.", 79 | "news_list_read_more_text": "තව කියවන්න", 80 | "case_item_local": "දේශීය", 81 | "case_item_foreign": "විදේශිය", 82 | "case_item_community": "ප්\u200Dරජාව", 83 | "case_item_quarantine": "නිරෝධායනය", 84 | "case_item_reported_locations": "වාර්තා වූ ස්ථානය", 85 | "case_item_register": " ලියාපදිංචි වන්න", 86 | "case_item_already_register": "දැනටමත් ලියාපදිංචිවී ඇත", 87 | "medical_consultation_service_title": "වෛද්\u200Dය උපදේශන සේවාවන්", 88 | "medical_consultation_service_foc": "මුදල් අයකිරීමකින් තොරයි.", 89 | "medical_emergency": "හදිසි හෝ තදබල රෝග සඳහා ගිලන්රථ,", 90 | "health_information": "වෛද්\u200Dය උපදෙස්", 91 | "covid_19_information": "Covid-19 ආශ්\u200Dරිත පැමිණිලි", 92 | "pharmacy_list": "ආසන්නයේ ඇති ෆාමසි සොයා ගැනීමට", 93 | "pharmacy_tab": "ෆාමසි", 94 | "scan_qr": "සුවෙන් සිටිමු QR", 95 | "qr_title":"සුවෙන් සිටිමු!", 96 | "qr_instruct":"QR කේතය හසුකරගන්න" 97 | } 98 | 99 | -------------------------------------------------------------------------------- /assets/lang/ta.json: -------------------------------------------------------------------------------- 1 | { 2 | "language_screen_choose": "விருப்பமான மொழியைத் தேர்வுசெய்க", 3 | "language_screen_choose_sub": "ஒரு மொழியைத் தெரிக", 4 | "welcome_screen_language_button_text": "தமிழ்", 5 | "welcome_screen_button_text": "அடுத்தது", 6 | "dashboard_welcome_title": "நல்வரவு", 7 | "dashboard_latest_figures_title": "புள்ளிவிவரங்கள்", 8 | "dashboard_confirmed_card_text": "உறுதிசெய்யப்பட்டவர்கள்", 9 | "dashboard_suspected_card_text": "சந்தேகத்திற்குரியவர்கள்", 10 | "dashboard_recovered_card_text": "உடல் நலம் குணமடைந்தவர்கள்", 11 | "dashboard_deaths_card_text": "மரணித்தவர்கள்", 12 | "dashboard_last_updated_text": "இறுதியாக புதுப்பிக்கப்பட்டது : ", 13 | "dashboard_news_text": "செய்திகள்", 14 | "dashboard_home_tab_text": "முற்பகுதி", 15 | "dashboard_location_tab_text": "எனது இருப்பிடம்", 16 | "dashboard_safe_track_tab_text": "நோயாளியின் பயணம்", 17 | "dashboard_case_list_tab_text": "சம்பவங்கள்", 18 | "dashboard_contact_tab_text": "டெலிஹெல்த்", 19 | "dashboard_register_tab_text": "பதிவு செய்க", 20 | "user_register_bar_title_text": "பதிவு செய்க", 21 | "user_register_screen_title": "பதிவு செய்க", 22 | "user_register_screen_subtitle": "உறுதிப்படுத்தப்பட்ட சம்பவத்திற்கு அருகில் இருந்தீர்களா?", 23 | "user_register_screen_name": "பெயர்", 24 | "user_register_screen_age": "வயது", 25 | "user_register_screen_email": "மின்னஞ்சல்", 26 | "user_register_screen_phone": "கைபேசி எண்", 27 | "user_register_screen_invalid_name": "சரியான பெயரை உள்ளிடவும்", 28 | "user_register_screen_invalid_age": "சரியான வயதை உள்ளிடவும்", 29 | "user_register_screen_invalid_number": "சரியான எண்ணை உள்ளிடவும்", 30 | "user_register_screen_invalid_email": "சரியான மின்னஞ்சல் முகவரியை உள்ளிடவும்", 31 | "user_register_screen_selected_text": "நிகழ்வுகள் சேர்க்கப்பட்டன", 32 | "user_register_screen_add_text": "+ மேலும் சேர்க்கவும்", 33 | "user_registration_screen_no_text": "சம்பவங்கள் எதுவும் இல்லை", 34 | "case_list_screen_search": "தேடல்", 35 | "case_list_screen_remove_text": "அகற்று", 36 | "cse_list_screen_see-text": "சேர்க்கப்பட்டது", 37 | "############": "####################################", 38 | "welcome_screen_subtitle": "ஒன்றாக நாம் கோவிட்-19 ஐ தோற்கடிக்க முடியும்", 39 | "dashboard_screen_title": "தகவல் பலகை", 40 | "dashboard_screen_welcome_message": "டாஷ்போர்டு", 41 | "dashboard_screen_data_received": "தரவு பெறப்பட்டது", 42 | "dashboard_screen_news_button": "செய்தியைத் தேர்ந்தெடுக்க", 43 | "dashboard_screen_case_list_button": "நோயாளி பட்டியல்", 44 | "dashboard_screen_case_details_button": "நோயாளி விவரங்கள்", 45 | "dashboard_screen_contact_us_button": "எங்களை தொடர்பு கொள்ள", 46 | "dashboard_screen_privacy_policy_button": "தனியுரிமைக் கொள்கை", 47 | "contact_us_screen_contact_us_title": "தொடர்பில் இருங்கள்", 48 | "dashboard_screen_ok_button": "சரி", 49 | "case_details_screen_title": "நோயாளி விவரங்கள்", 50 | "ui_general_next": "அடுத்தது", 51 | "ui_general_welcome": "நல்வரவு", 52 | "news_detail_page_title": "பதிக", 53 | "welcome_screen_tamil_button_text": "தமிழ்", 54 | "dashboard_screen_figures": "சமீபத்திய புள்ளிவிவரங்கள் இங்கே", 55 | "dashboard_screen_confirmed": "உறுதியாக", 56 | "dashboard_screen_suspected": "சந்தேகத்திற்குரிய", 57 | "dashboard_screen_recovered": "மீட்கப்பட்ட", 58 | "dashboard_screen_deaths": "மீட்கப்பட்ட", 59 | "dashboard_screen_news": "செய்திகள்", 60 | "dashboard_screen_last_updated": "கடைசியாக புதுப்பிக்கப்பட்டது", 61 | "popmenu_language": "மொழி", 62 | "popmenu_faq": "அடிக்கடி கேட்கப்படும் கேள்விகள்", 63 | "popmenu_ios_faq": "அடிக்கடி கேட்கப்படும் கேள்விகள்", 64 | "popmenu_privpolicy": "தனியுரிமைக் கொள்கை", 65 | "faq": { 66 | "\"கொரோனா வைரஸ் என்றால் என்ன?\"": "\"கொரோனா வைரஸ்கள் ஒரு பெரிய குடும்ப வைரஸ்கள், அவை விலங்குகள் அல்லது மனிதர்களுக்கு நோயை ஏற்படுத்தக்கூடும். மனிதர்களில், பல கொரோனா வைரஸ்கள் பொதுவான சளி முதல் மத்திய கிழக்கு சுவாச நோய்க்குறி (மெர்ஸ்) மற்றும் கடுமையான சுவாச நோய்க்குறி (SARS) போன்ற சுவாச நோய்த்தொற்றுகளை ஏற்படுத்தும் என்று அறியப்படுகிறது. மிக சமீபத்தில் கண்டுபிடிக்கப்பட்ட கொரோனா வைரஸ் கொரோனா வைரஸ் நோயான COVID-19 ஐ ஏற்படுத்துகிறது\"", 67 | "\"COVID -19 என்றால் என்ன?\"": "\"COVID-19 என்பது சமீபத்தில் கண்டுபிடிக்கப்பட்ட கொரோனா வைரஸால் ஏற்படும் தொற்று நோய். சீனாவின் வுஹானில் 2019 டிசம்பரில் பெரும்பரவல் தொடங்குவதற்கு முன்பு வரை இந்த புதிய வைரஸ் மற்றும் நோய் பற்றி அறியப்பட்டிருக்கவில்லை.\"", 68 | "\"COVID-19 இன் அறிகுறிகள் யாவை?\"": "\"COVID-19 இன் பொதுவான அறிகுறிகள் காய்ச்சல், சோர்வு மற்றும் வறட்டு இருமல். சில நோயாளிகளுக்கு கடுப்பு மற்றும் வலிகள், மூக்கடைப்பு, மூக்கு ஒழுகுதல், தொண்டை புண் அல்லது வயிற்றுப்போக்கு இருக்கலாம். இந்த அறிகுறிகள் பொதுவாக லேசானவை மற்றும் படிப்படியாக தொடங்கும். சிலர் நோய்த்தொற்றுக்கு ஆளாகிறார்கள், ஆனால் எந்த அறிகுறிகளையும் உருவாக மாட்டாது. பெரும்பாலான மக்கள் (சுமார் 80%) சிறப்பு சிகிச்சை தேவையில்லாமல் நோயிலிருந்து மீண்டு வருகிறார்கள். COVID-19 பெறும் ஒவ்வொரு 6 பேரில் 1 பேர் கடுமையாக நோய்வாய்ப்பட்டு மூச்சு விடுவதில் சிரமத்தை உருவாக்குகிறார்கள். வயதானவர்கள், மற்றும் உயர் இரத்த அழுத்தம், இதய பிரச்சினைகள் அல்லது நீரிழிவு போன்ற மருத்துவ பிரச்சினைகள் உள்ளவர்களுக்கு கடுமையான நோய் வருவதற்கான வாய்ப்புகள் அதிகம். காய்ச்சல், இருமல் மற்றும் சுவாசிப்பதில் சிரமம் உள்ளவர்கள் மருத்துவ சிகிச்சை பெற வேண்டும்\"", 69 | "\"COVID-19 எவ்வாறு பரவுகிறது?\"": "\"வைரஸ் உள்ள மற்றவர்களிடமிருந்து COVID-19 பரவலாம். COVID-19 இருமல் அல்லது சுவாசிக்கும்போது ஒரு நபர் மூக்கு அல்லது வாயிலிருந்து சிறிய நீர்த்துளிகள் மூலம் இந்த நோய் பரவுகிறது. இந்த நீர்த்துளிகள் நபரைச் சுற்றியுள்ள பொருள்கள் மற்றும் பரப்புகளில் இறங்குகின்றன. மற்றவர்கள் COVID-19 ஐ இந்த பொருள்கள் அல்லது மேற்பரப்புகளைத் தொட்டு, பின்னர் அவர்களின் கண்கள், மூக்கு அல்லது வாயைத் தொடுவதன் மூலம் பிடிக்கிறார்கள். COVID-19 உடைய ஒருவரிடமிருந்து நீர்த்துளிகள் சுவாசித்தால் மக்கள் COVID- 19 இனால் பீடிக்கலாம். இதனால்தான் நோய்வாய்ப்பட்ட ஒருவரிடமிருந்து 1 மீட்டருக்கு (3 அடி) அதிகமாக இருக்க வேண்டியது அவசியம்.\"", 70 | "\"COVID -19 ஐ ஏற்படுத்தும் வைரஸ் காற்று வழியாக பரவ முடியுமா?\"": "\"COVID-19 ஐ ஏற்படுத்தும் வைரஸ் முக்கியமாக காற்று வழியாக இல்லாமல் சுவாச துளிகளுடன் தொடர்பு கொள்வதன் மூலம் பரவுகிறது என்று இன்றுவரை ஆய்வுகள் தெரிவிக்கின்றன. “COVID-19"எவ்வாறு பரவுகிறது" என்ற பதிலைப் பார்க்க.\"", 71 | "\"அறிகுறிகள் இல்லாத ஒருவரிடமிருந்து COVID-19 பிடிக்க முடியுமா?\"": "\"இருமல் உள்ள ஒருவரால் வெளியேற்றப்படும் சுவாச துளிகள் நோய் பரவுவதற்கான முக்கிய வழி. அறிகுறிகள் இல்லாத ஒருவரிடமிருந்து COVID-19 ஐப் பீடிக்கும் ஆபத்து மிகக் குறைவு. இருப்பினும், COVID-19 உள்ள பலர் லேசான அறிகுறிகளை மட்டுமே அனுபவிக்கின்றனர். நோயின் ஆரம்ப கட்டங்களில் இது குறிப்பாக உண்மை. ஆகவே, எடுத்துக்காட்டாக, லேசான இருமல் மற்றும் உடல்நிலை சற்று குறைந்தவரிடமிருந்து COVID-19 பீடிக்க முடியும். COVID-19 பரவும் காலம் குறித்த தற்போதைய ஆராய்ச்சியை WHO மதிப்பிடுகிறது, மேலும் புதுப்பிக்கப்பட்ட கண்டுபிடிப்புகளை தொடர்ந்து பகிர்ந்து கொள்ளும்.\"", 72 | "\"நோயால் பாதிக்கப்பட்ட ஒருவரின் மலத்திலிருந்து எனக்கு COVID-19 பீடிக்க முடியுமா?\"": "\"பாதிக்கப்பட்ட நபரின் மலத்திலிருந்து COVID-19 பீடிக்கும் ஆபத்து குறைவாக இருப்பதாகத் தெரிகிறது. ஆரம்ப விசாரணைகள் சில சந்தர்ப்பங்களில் மலத்தில் வைரஸ் இருக்கலாம் என்று கூறினாலும், இந்த பாதை வழியாக பரவுவது நோய்ப் பரவலின் முக்கிய அம்சம் அல்ல. COVID-19 பரவியுள்ள வழிகள் குறித்த புதிய ஆராய்ச்சிகளை WHO மதிப்பிடுகிறது, மேலும் புதிய கண்டுபிடிப்புகளை தொடர்ந்து பகிர்ந்து கொள்ளும். இதுவும் ஒரு ஆபத்து என்பதால், கழிப்பறையைப் பயன்படுத்தியபின்னும், சாப்பிடுவதற்கு முன்பும் தவறாமல் கைகளை சுத்தம் செய்வது சிறந்ததாகும்.\"" 73 | }, 74 | "home_address": "வீட்டு முகவரி", 75 | "sri_lankan_citizan": "நீங்கள் இலங்கையரா?", 76 | "radio_yes": "ஆம்", 77 | "radio_no": "இல்லை", 78 | "nic_no": "தேசிய அடையாள அட்டை எண்", 79 | "select_a_gender": "பாலினத்தைத் தேர்ந்தெடுக்கவும்r", 80 | "menu_item_male": "ஆண்", 81 | "menu_item_female": "பெண்", 82 | "menu_item_other": "மற்றவை", 83 | "register": "பதிவு செய்க", 84 | "passport_number": "கடவுச்சீட்டு எண்", 85 | "tos_decline_button": "மறுக்கிறேன்", 86 | "tos_dialog_title": "நிபந்தனை விதிமுறைகள்", 87 | "tos_accept_button": "நான் ஏற்றுக்கொள்கிறேன்", 88 | "tos_title": "MyHealth Sri Lanka பயன்பாட்டைப் பயன்படுத்துவதன் மூலம், எனக்கு புரிவதாவது", 89 | "tos_line_one": "பயன்பாடு எனது இருப்பிடத் தரவை எனது மொபைல் சாதனத்தில் பாதுகாப்பாக பதிவு செய்யும், எனது சரியான முன் அனுமதியின்றி பதிவுசெய்யப்பட்ட இருப்பிடத் தரவு சாதனத்திலிருந்து மாற்றப்படாது.", 90 | "tos_line_two": "இந்த பயன்பாடு எனது பதிவுசெய்யப்பட்ட தனிப்பட்ட தகவல்களை இலங்கை சுகாதார இலங்கை அமைச்சகத்திற்கு சொந்தமான மற்றும் நிர்வகிக்கப்படும் மேகக்கட்டத்தில் பாதுகாப்பாக சேமிக்கும்\n.", 91 | "news_list_read_more_text": "மேலும் வாசிக்க", 92 | "case_item_local": "உள்நாட்டவர்", 93 | "case_item_foreign": "வெளிநாட்டவர்", 94 | "case_item_community": "சமூகம்", 95 | "case_item_quarantine": "தனிமைப்படுத்தல்", 96 | "case_item_reported_locations": "அறிவிக்கப்பட்ட இடங்கள்", 97 | "case_item_register": "பதிக", 98 | "case_item_already_register": "பதிவுக்கு ஏற்கனவே சேர்க்கப்பட்டது", 99 | "medical_consultation_service_title": "மருத்துவ ஆலோசனை சேவைகள்", 100 | "medical_consultation_service_foc": "கட்டணம் இல்லாமல்", 101 | 102 | "medical_emergency": "திடீர் அல்லது கடுமையான நோய்க்கான ஆம்புலன்ஸ்", 103 | "health_information": "சுகாதார தகவல்", 104 | "covid_19_information": "கோவிட் -19 தொடர்புடைய புகார்கள்", 105 | "pharmacy_list": "அருகிலுள்ள மருத்தக விநியோக சேவையைக் கண்டறிக", 106 | "pharmacy_tab": "மருந்தகம்", 107 | "scan_qr": "பாதுகாப்பாக இரு QR", 108 | "qr_title":"பாதுகாப்பாக இருப்போம்!", 109 | "qr_instruct":"QR குறியீட்டைப் பிடிக்கவும்" 110 | } 111 | 112 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def parse_KV_file(file, separator='=') 14 | file_abs_path = File.expand_path(file) 15 | if !File.exists? file_abs_path 16 | return []; 17 | end 18 | generated_key_values = {} 19 | skip_line_start_symbols = ["#", "/"] 20 | File.foreach(file_abs_path) do |line| 21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } 22 | plugin = line.split(pattern=separator) 23 | if plugin.length == 2 24 | podname = plugin[0].strip() 25 | path = plugin[1].strip() 26 | podpath = File.expand_path("#{path}", file_abs_path) 27 | generated_key_values[podname] = podpath 28 | else 29 | puts "Invalid plugin specification: #{line}" 30 | end 31 | end 32 | generated_key_values 33 | end 34 | 35 | target 'Runner' do 36 | use_frameworks! 37 | use_modular_headers! 38 | 39 | # Flutter Pod 40 | 41 | copied_flutter_dir = File.join(__dir__, 'Flutter') 42 | copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework') 43 | copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec') 44 | unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path) 45 | # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet. 46 | # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration. 47 | # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist. 48 | 49 | generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig') 50 | unless File.exist?(generated_xcode_build_settings_path) 51 | raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first" 52 | end 53 | generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path) 54 | cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR']; 55 | 56 | unless File.exist?(copied_framework_path) 57 | FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir) 58 | end 59 | unless File.exist?(copied_podspec_path) 60 | FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir) 61 | end 62 | end 63 | 64 | # Keep pod path relative so it can be checked into Podfile.lock. 65 | pod 'Flutter', :path => 'Flutter' 66 | 67 | # Plugin Pods 68 | 69 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock 70 | # referring to absolute paths on developers' machines. 71 | system('rm -rf .symlinks') 72 | system('mkdir -p .symlinks/plugins') 73 | plugin_pods = parse_KV_file('../.flutter-plugins') 74 | plugin_pods.each do |name, path| 75 | symlink = File.join('.symlinks', 'plugins', name) 76 | File.symlink(path, symlink) 77 | pod name, :path => File.join(symlink, 'ios') 78 | end 79 | end 80 | 81 | # Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system. 82 | install! 'cocoapods', :disable_input_output_paths => true 83 | 84 | post_install do |installer| 85 | installer.pods_project.targets.each do |target| 86 | target.build_configurations.each do |config| 87 | config.build_settings['ENABLE_BITCODE'] = 'NO' 88 | end 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | 7 | override func application( 8 | _ application: UIApplication, 9 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 10 | ) -> Bool { 11 | 12 | // Messaging 13 | if #available(iOS 10.0, *) { 14 | UNUserNotificationCenter.current().delegate = self 15 | } 16 | 17 | GeneratedPluginRegistrant.register(with: self) 18 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : "1", 4 | "author" : "Iconizer" 5 | }, 6 | "images" : [ 7 | { 8 | "filename" : "Icon-1024.png", 9 | "idiom" : "ios-marketing", 10 | "scale" : "1x", 11 | "size" : "1024x1024" 12 | }, 13 | { 14 | "filename" : "Icon-83.5@2x.png", 15 | "idiom" : "ipad", 16 | "scale" : "2x", 17 | "size" : "83.5x83.5" 18 | }, 19 | { 20 | "filename" : "Icon-76@2x.png", 21 | "idiom" : "ipad", 22 | "scale" : "2x", 23 | "size" : "76x76" 24 | }, 25 | { 26 | "filename" : "Icon-76.png", 27 | "idiom" : "ipad", 28 | "scale" : "1x", 29 | "size" : "76x76" 30 | }, 31 | { 32 | "filename" : "Icon-60@3x.png", 33 | "idiom" : "iphone", 34 | "scale" : "3x", 35 | "size" : "60x60" 36 | }, 37 | { 38 | "filename" : "Icon-60@2x.png", 39 | "idiom" : "iphone", 40 | "scale" : "2x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "filename" : "Icon-40@2x.png", 45 | "idiom" : "ipad", 46 | "scale" : "2x", 47 | "size" : "40x40" 48 | }, 49 | { 50 | "filename" : "Icon-40@2x.png", 51 | "idiom" : "iphone", 52 | "scale" : "2x", 53 | "size" : "40x40" 54 | }, 55 | { 56 | "filename" : "Icon-40@3x.png", 57 | "idiom" : "iphone", 58 | "scale" : "3x", 59 | "size" : "40x40" 60 | }, 61 | { 62 | "filename" : "Icon-40.png", 63 | "idiom" : "ipad", 64 | "scale" : "1x", 65 | "size" : "40x40" 66 | }, 67 | { 68 | "filename" : "Icon-29@2x.png", 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "29x29" 72 | }, 73 | { 74 | "filename" : "Icon-29@2x.png", 75 | "idiom" : "iphone", 76 | "scale" : "2x", 77 | "size" : "29x29" 78 | }, 79 | { 80 | "filename" : "Icon-29@3x.png", 81 | "idiom" : "iphone", 82 | "scale" : "3x", 83 | "size" : "29x29" 84 | }, 85 | { 86 | "filename" : "Icon-29.png", 87 | "idiom" : "ipad", 88 | "scale" : "1x", 89 | "size" : "29x29" 90 | }, 91 | { 92 | "filename" : "Icon-29.png", 93 | "idiom" : "iphone", 94 | "scale" : "1x", 95 | "size" : "29x29" 96 | }, 97 | { 98 | "filename" : "Icon-20@2x.png", 99 | "idiom" : "ipad", 100 | "scale" : "2x", 101 | "size" : "20x20" 102 | }, 103 | { 104 | "filename" : "Icon-20@2x.png", 105 | "idiom" : "iphone", 106 | "scale" : "2x", 107 | "size" : "20x20" 108 | }, 109 | { 110 | "filename" : "Icon-20@3x.png", 111 | "idiom" : "iphone", 112 | "scale" : "3x", 113 | "size" : "20x20" 114 | }, 115 | { 116 | "filename" : "Icon-20.png", 117 | "idiom" : "ipad", 118 | "scale" : "1x", 119 | "size" : "20x20" 120 | } 121 | ] 122 | } -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-1024.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-20.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-29.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-40.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-76.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/GoogleService-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CLIENT_ID 6 | 1096700657713-n1lvbkr36hm2pa1u758q5gms0hnf49c7.apps.googleusercontent.com 7 | REVERSED_CLIENT_ID 8 | com.googleusercontent.apps.1096700657713-n1lvbkr36hm2pa1u758q5gms0hnf49c7 9 | API_KEY 10 | AIzaSyC_Jwk322CBPdMNtwHxD0nXAvkb66VAdiE 11 | GCM_SENDER_ID 12 | 1096700657713 13 | PLIST_VERSION 14 | 1 15 | BUNDLE_ID 16 | app.ceylon.selftrackingapp 17 | PROJECT_ID 18 | covid-19-lk-dev 19 | STORAGE_BUCKET 20 | covid-19-lk-dev.appspot.com 21 | IS_ADS_ENABLED 22 | 23 | IS_ANALYTICS_ENABLED 24 | 25 | IS_APPINVITE_ENABLED 26 | 27 | IS_GCM_ENABLED 28 | 29 | IS_SIGNIN_ENABLED 30 | 31 | GOOGLE_APP_ID 32 | 1:1096700657713:ios:3bfdaf3aad640d3a9b5510 33 | DATABASE_URL 34 | https://covid-19-lk-dev.firebaseio.com 35 | 36 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleDisplayName 14 | MyHealth Sri Lanka 15 | CFBundleName 16 | MyHealth Sri Lanka 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | NSLocationAlwaysAndWhenInUseUsageDescription 28 | We need your location information to check whether you were present in any contaminated area 29 | NSLocationAlwaysUsageDescription 30 | We need your location information to check whether you were present in any contaminated area 31 | NSLocationWhenInUseUsageDescription 32 | We need your location information to check whether you were present in any contaminated area 33 | UILaunchStoryboardName 34 | LaunchScreen 35 | UIMainStoryboardFile 36 | Main 37 | UISupportedInterfaceOrientations 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationLandscapeLeft 41 | UIInterfaceOrientationLandscapeRight 42 | 43 | UISupportedInterfaceOrientations~ipad 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationPortraitUpsideDown 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | UIViewControllerBasedStatusBarAppearance 51 | 52 | io.flutter.embedded_views_preview 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /ios/Runner/Location.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Location.swift 3 | // Runner 4 | // 5 | // Created by Udesh Kumarasinghe on 3/15/20. 6 | // Copyright © 2020 The Chromium Authors. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreLocation 11 | 12 | class Location: Codable { 13 | 14 | let latitude: Double 15 | let longitude: Double 16 | let recordedAt: Int 17 | let date: Date 18 | let title: String 19 | 20 | init(_ location: CLLocationCoordinate2D, date: Date) { 21 | latitude = location.latitude 22 | longitude = location.longitude 23 | self.date = date 24 | recordedAt = Int(date.timeIntervalSince1970) 25 | title = Location.dateFormatter.string(from: date) 26 | } 27 | 28 | static let dateFormatter: DateFormatter = { 29 | let formatter = DateFormatter() 30 | formatter.dateStyle = .medium 31 | formatter.timeStyle = .short 32 | return formatter 33 | }() 34 | 35 | } 36 | -------------------------------------------------------------------------------- /ios/Runner/LocationStore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LocationStore.swift 3 | // Runner 4 | // 5 | // Created by Udesh Kumarasinghe on 3/15/20. 6 | // Copyright © 2020 The Chromium Authors. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreLocation 11 | 12 | class LocationsStorage { 13 | static let shared = LocationsStorage() 14 | 15 | private(set) var locations: [Location] 16 | private let fileManager: FileManager 17 | private let documentsURL: URL 18 | 19 | init() { 20 | let fileManager = FileManager.default 21 | documentsURL = try! fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) 22 | self.fileManager = fileManager 23 | 24 | let jsonDecoder = JSONDecoder() 25 | 26 | let locationFilesURLs = try! fileManager.contentsOfDirectory(at: documentsURL, 27 | includingPropertiesForKeys: nil) 28 | locations = locationFilesURLs.compactMap { url -> Location? in 29 | guard !url.absoluteString.contains(".DS_Store") else { 30 | return nil 31 | } 32 | guard let data = try? Data(contentsOf: url) else { 33 | return nil 34 | } 35 | return try? jsonDecoder.decode(Location.self, from: data) 36 | }.sorted(by: { $0.date < $1.date }) 37 | } 38 | 39 | func saveLocationOnDisk(location: Location) { 40 | let encoder = JSONEncoder() 41 | let timestamp = location.date.timeIntervalSince1970 42 | let fileURL = documentsURL.appendingPathComponent("\(timestamp)") 43 | 44 | let data = try! encoder.encode(location) 45 | try! data.write(to: fileURL) 46 | 47 | locations.append(location) 48 | } 49 | } 50 | 51 | 52 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" -------------------------------------------------------------------------------- /ios/Runner/Runner.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aps-environment 6 | development 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/app_localizations.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:convert'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter/services.dart'; 6 | import 'package:shared_preferences/shared_preferences.dart'; 7 | 8 | class AppLocalizations { 9 | Locale locale; 10 | 11 | AppLocalizations(this.locale); 12 | 13 | // Helper method to keep the code in the widgets concise 14 | // Localizations are accessed using an InheritedWidget "of" syntax 15 | static AppLocalizations of(BuildContext context) { 16 | return Localizations.of(context, AppLocalizations); 17 | } 18 | 19 | // Static member to have a simple access to the delegate from the MaterialApp 20 | static const LocalizationsDelegate delegate = 21 | _AppLocalizationsDelegate(); 22 | 23 | Map _localizedStrings; 24 | 25 | Future load(Locale locale) async { 26 | this.locale = locale; 27 | // Save the language preference 28 | SharedPreferences prefs = await SharedPreferences.getInstance(); 29 | prefs.setString('preferred_language', locale.languageCode); 30 | // Load the language JSON file from the "lang" folder 31 | 32 | //Files should be initially stored in the an array and not read every single time. 33 | String jsonString = 34 | await rootBundle.loadString('assets/lang/${locale.languageCode}.json'); 35 | Map jsonMap = json.decode(jsonString); 36 | _localizedStrings = jsonMap.map((key, value) { 37 | return MapEntry(key, value.toString()); 38 | }); 39 | return true; 40 | } 41 | 42 | // This method will be called from every widget which needs a localized text 43 | String translate(String key) { 44 | return _localizedStrings[key]; 45 | } 46 | } 47 | 48 | // LocalizationsDelegate is a factory for a set of localized resources 49 | // In this case, the localized strings will be gotten in an AppLocalizations object 50 | class _AppLocalizationsDelegate 51 | extends LocalizationsDelegate { 52 | // This delegate instance will never change (it doesn't even have fields!) 53 | // It can provide a constant constructor. 54 | const _AppLocalizationsDelegate(); 55 | 56 | @override 57 | bool isSupported(Locale locale) { 58 | // Include all of your supported language codes here 59 | return ['en', 'si', 'ta'].contains(locale.languageCode); 60 | } 61 | 62 | @override 63 | Future load(Locale locale) async { 64 | // AppLocalizations class is where the JSON loading actually runs 65 | AppLocalizations localizations = new AppLocalizations(locale); 66 | await localizations.load(locale); 67 | return localizations; 68 | } 69 | 70 | @override 71 | bool shouldReload(_AppLocalizationsDelegate old) => false; 72 | } 73 | -------------------------------------------------------------------------------- /lib/constants.dart: -------------------------------------------------------------------------------- 1 | final bool debugRelease = false; 2 | //final String testingServer = "https://test.covid-19.health.gov.lk/api"; 3 | final String testingServer = "https://test.covid-19.health.gov.lk/api"; 4 | 5 | //Constants defined for version checking 6 | const String ANDROID_APP_BUILD_NUMBER_KEY = "android_app_builder_number_Key"; 7 | const String IOS_APP_BUILD_NUMBER_KEY = "ios_app_builder_number_key"; 8 | const String ANDROID_APP_URL = 9 | "https://play.google.com/store/apps/details?id=app.ceylon.selftrackingapp"; 10 | const String IOS_APP_URL = 11 | "https://apps.apple.com/us/app/myhealth-sri-lanka/id1503349513"; 12 | -------------------------------------------------------------------------------- /lib/exceptions/data_fetch_exception.dart: -------------------------------------------------------------------------------- 1 | class DataFetchException implements Exception { 2 | String errormsg; 3 | DataFetchException(this.errormsg); 4 | } 5 | -------------------------------------------------------------------------------- /lib/exceptions/data_write_exception.dart: -------------------------------------------------------------------------------- 1 | class DataWriteException implements Exception { 2 | String errormsg; 3 | DataWriteException(this.errormsg); 4 | } 5 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:connectivity/connectivity.dart'; 4 | import 'package:dropdown_banner/dropdown_banner.dart'; 5 | import 'package:flutter/cupertino.dart'; 6 | import 'package:flutter/material.dart'; 7 | import 'package:flutter/services.dart'; 8 | import 'package:flutter_localizations/flutter_localizations.dart'; 9 | import 'package:get_it/get_it.dart'; 10 | import 'package:selftrackingapp/app_localizations.dart'; 11 | import 'package:selftrackingapp/networking/data_repository.dart'; 12 | import 'package:selftrackingapp/networking/db.dart'; 13 | import 'package:selftrackingapp/page/screen/root_screen.dart'; 14 | import 'package:selftrackingapp/page/screen/welcome_screen.dart'; 15 | import 'package:shared_preferences/shared_preferences.dart'; 16 | 17 | import 'utils/tracker_colors.dart'; 18 | 19 | void main() { 20 | runApp(MyApp()); 21 | } 22 | 23 | class MyApp extends StatefulWidget { 24 | @override 25 | _MyAppState createState() => _MyAppState(); 26 | } 27 | 28 | class _MyAppState extends State { 29 | @override 30 | void initState() { 31 | super.initState(); 32 | GetIt.instance 33 | .registerSingleton(AppDataRepository(AppDatabase())); 34 | } 35 | 36 | @override 37 | Widget build(BuildContext context) { 38 | final navigatorKey = GlobalKey(); 39 | 40 | return MaterialApp( 41 | debugShowCheckedModeBanner: false, 42 | title: 'COVID-19 Tracker', 43 | theme: ThemeData( 44 | primarySwatch: TrackerColors.primaryColor, 45 | backgroundColor: Color(0xfff6f6f9), 46 | textTheme: TextTheme( 47 | display1: TextStyle(color: Colors.black, fontSize: 15.0), 48 | display2: TextStyle(color: Colors.black54, fontSize: 12.0), 49 | body1: TextStyle(color: Colors.black54, fontSize: 15.0), 50 | )), 51 | supportedLocales: [Locale('en', "US"), Locale('si', "LK")], 52 | localizationsDelegates: [ 53 | // A class which loads the translations from JSON files 54 | AppLocalizations.delegate, 55 | // Built-in localization of basic text for Material widgets 56 | GlobalMaterialLocalizations.delegate, 57 | // Built-in localization for text direction LTR/RTL 58 | GlobalWidgetsLocalizations.delegate, 59 | ], 60 | home: DropdownBanner( 61 | child: HomeScreen(), 62 | navigatorKey: navigatorKey, 63 | ), 64 | ); 65 | } 66 | } 67 | 68 | class HomeScreen extends StatefulWidget { 69 | @override 70 | _HomeScreenState createState() => _HomeScreenState(); 71 | } 72 | 73 | class _HomeScreenState extends State { 74 | static const Duration SPLASH_DURATION = Duration(seconds: 3); 75 | Widget _nextScreen; 76 | bool _isTimeoutCompleted; 77 | 78 | @override 79 | void initState() { 80 | super.initState(); 81 | 82 | _isTimeoutCompleted = false; 83 | SystemChrome.setPreferredOrientations([ 84 | DeviceOrientation.portraitUp, 85 | DeviceOrientation.portraitDown, 86 | ]); 87 | Timer(SPLASH_DURATION, () { 88 | if (_nextScreen != null) { 89 | Navigator.of(context) 90 | .pushReplacement(MaterialPageRoute(builder: (_) => _nextScreen)); 91 | } else { 92 | _isTimeoutCompleted = true; 93 | } 94 | }); 95 | 96 | loadLang(); 97 | } 98 | 99 | Future loadLang() async { 100 | final SharedPreferences pref = await SharedPreferences.getInstance(); 101 | 102 | String language = pref.getString("language"); 103 | if (language != null) { 104 | if (language == "en") { 105 | AppLocalizations.of(context).load(Locale("en", "US")); 106 | } else if (language == "ta") { 107 | AppLocalizations.of(context).load(Locale("ta", "TA")); 108 | } else { 109 | AppLocalizations.of(context).load(Locale("si", "LK")); 110 | } 111 | _nextScreen = RootScreen(); 112 | if (_isTimeoutCompleted) { 113 | Navigator.of(context) 114 | .pushReplacement(MaterialPageRoute(builder: (_) => _nextScreen)); 115 | } 116 | } else { 117 | _nextScreen = WelcomeScreen(); 118 | if (_isTimeoutCompleted) { 119 | Navigator.of(context) 120 | .pushReplacement(MaterialPageRoute(builder: (_) => _nextScreen)); 121 | } 122 | } 123 | } 124 | 125 | Widget _createSplashScreen() { 126 | return Container( 127 | decoration: BoxDecoration( 128 | image: DecorationImage( 129 | image: AssetImage("assets/images/welcome_screen_bg.png"), 130 | fit: BoxFit.fill)), 131 | ); // or some other widget 132 | } 133 | 134 | void reachabilityFailedFail() { 135 | DropdownBanner.showBanner( 136 | text: 'Please check your WiFi or mobile data connection', 137 | color: Colors.redAccent, 138 | textStyle: TextStyle(color: Colors.white), 139 | duration: Duration(seconds: 3)); 140 | } 141 | 142 | void checkReachability() async { 143 | var connectivityResult = await (Connectivity().checkConnectivity()); 144 | if (connectivityResult == ConnectivityResult.mobile) { 145 | } else if (connectivityResult == ConnectivityResult.wifi) { 146 | // I am connected to a wifi network. 147 | } else { 148 | reachabilityFailedFail(); 149 | } 150 | } 151 | 152 | @override 153 | Widget build(BuildContext context) { 154 | checkReachability(); 155 | return _createSplashScreen(); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /lib/models/contact_us_contact.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | class ContactUsContact { 4 | int id; 5 | String title; 6 | String subTitle; 7 | String address; 8 | String link; 9 | bool titleTranslate; 10 | bool subtitleTranslate; 11 | List subContacts; 12 | 13 | ContactUsContact._(); 14 | 15 | factory ContactUsContact.fromJSON(Map jsonData) { 16 | // print(jsonData); 17 | ContactUsContact contact = ContactUsContact._(); 18 | contact.id = jsonData['id']; 19 | contact.title = jsonData['title']; 20 | contact.subTitle = jsonData['sub_title']; 21 | contact.link = jsonData['link']; 22 | contact.address = jsonData['address']; 23 | contact.titleTranslate = jsonData['title_translate']; 24 | contact.subtitleTranslate = jsonData['subtitle_translate']; 25 | 26 | if (jsonData["sub"] != null) { 27 | List subContacts = List(); 28 | for (var subContact in jsonData["sub"]) { 29 | subContacts.add(ContactUsContact.fromJSON(subContact)); 30 | } 31 | contact.subContacts = subContacts; 32 | } 33 | 34 | return contact; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/models/data_type.dart: -------------------------------------------------------------------------------- 1 | enum DataType { News, Case } 2 | -------------------------------------------------------------------------------- /lib/models/fcm_message.dart: -------------------------------------------------------------------------------- 1 | class FCMMessage { 2 | String title; 3 | String body; 4 | String type; 5 | 6 | FCMMessage({this.title, this.body, this.type}); 7 | 8 | factory FCMMessage.decode(Map json) { 9 | return FCMMessage( 10 | title: json['notification']['title'], 11 | body: json['notification']['body'], 12 | type: json['data']['type']); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/models/location.dart: -------------------------------------------------------------------------------- 1 | import 'package:equatable/equatable.dart'; 2 | 3 | class Location extends Equatable { 4 | double longitude; 5 | double latitude; 6 | String address; 7 | DateTime date, from, to; 8 | 9 | Location({ 10 | this.longitude, 11 | this.latitude, 12 | this.address, 13 | this.date, 14 | this.from, 15 | this.to, 16 | }); 17 | 18 | factory Location.fromJson(Map json) { 19 | return Location( 20 | latitude: json["latitude"] == "" ? 0 : double.parse(json['latitude']), 21 | longitude: 22 | json["longitude"] == "" ? 0 : double.parse(json['longitude']), 23 | address: json['area'], 24 | date: DateTime.parse(json['date']), 25 | from: DateTime.now(), 26 | to: DateTime.now()); 27 | } 28 | 29 | factory Location.fromBackgroundJson(Map json) { 30 | return Location( 31 | latitude: json["latitude"], 32 | longitude: json["longitude"], 33 | address: json['address'], 34 | date: DateTime.fromMillisecondsSinceEpoch(json['recordedAt']), 35 | from: json['from'], 36 | to: json['to']); 37 | } 38 | 39 | @override 40 | // TODO: implement props 41 | List get props => [date]; 42 | } 43 | -------------------------------------------------------------------------------- /lib/models/message_type.dart: -------------------------------------------------------------------------------- 1 | enum MessageType { Critical, Warning, Info } 2 | -------------------------------------------------------------------------------- /lib/models/news_article.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:equatable/equatable.dart'; 4 | 5 | import 'data_type.dart'; 6 | import 'message_type.dart'; 7 | 8 | class NewsArticle extends Equatable { 9 | int id = -1; 10 | String photoUrl; 11 | String title = ""; 12 | String subtitle = ""; 13 | String originator = ""; 14 | String message = ""; 15 | DateTime created = DateTime.now(); 16 | MessageType messageType; 17 | DataType dataType; 18 | 19 | NewsArticle(); 20 | 21 | factory NewsArticle.fromJSON(Map data) { 22 | NewsArticle article = new NewsArticle(); 23 | String sid = data['id']; 24 | if (sid != null) { 25 | article.id = int.parse(sid); 26 | } 27 | article.title = data['title']; 28 | article.subtitle = data['subtitle']; 29 | article.originator = data['source'] ?? ''; 30 | article.message = data['message']; 31 | String dt = data['createdTime'] as String; 32 | if (dt != null) { 33 | article.created = DateTime.parse(dt); 34 | } 35 | article.photoUrl = data['feature_image']; 36 | switch (data['message_type']) { 37 | case "Critical": 38 | article.messageType = MessageType.Critical; 39 | break; 40 | case "Warning": 41 | article.messageType = MessageType.Warning; 42 | break; 43 | case "Info": 44 | article.messageType = MessageType.Info; 45 | break; 46 | } 47 | article.dataType = 48 | data["Data_type"] == "News" ? DataType.News : DataType.Case; 49 | return article; 50 | } 51 | 52 | @override 53 | // TODO: implement props 54 | List get props => [id]; 55 | } 56 | -------------------------------------------------------------------------------- /lib/models/registration.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | class Registration { 4 | final String name; 5 | final String email; 6 | final String address; 7 | final double lattitude; 8 | final double longitude; 9 | final String mobileImei; 10 | final List caseList; 11 | final String nic; 12 | final String passport; 13 | final String country; 14 | final String age; 15 | final String gender; 16 | Registration({ 17 | this.name, 18 | this.email, 19 | this.address, 20 | this.lattitude, 21 | this.longitude, 22 | this.mobileImei, 23 | this.caseList, 24 | this.nic = "", 25 | this.passport = "", 26 | this.country = "", 27 | this.age, 28 | this.gender, 29 | }); 30 | 31 | Registration copyWith({ 32 | String name, 33 | String email, 34 | String address, 35 | double lattitude, 36 | double longitude, 37 | String mobileImei, 38 | List caseList, 39 | String nic, 40 | String passport, 41 | String country, 42 | String age, 43 | String gender, 44 | }) { 45 | return Registration( 46 | name: name ?? this.name, 47 | email: email ?? this.email, 48 | address: address ?? this.address, 49 | lattitude: lattitude ?? this.lattitude, 50 | longitude: longitude ?? this.longitude, 51 | mobileImei: mobileImei ?? this.mobileImei, 52 | caseList: caseList ?? this.caseList, 53 | nic: nic ?? this.nic, 54 | passport: passport ?? this.passport, 55 | country: country ?? this.country, 56 | age: age ?? this.age, 57 | gender: gender ?? this.gender, 58 | ); 59 | } 60 | 61 | Map toMap() { 62 | Map map = { 63 | 'name': name, 64 | 'email': email, 65 | 'address': address, 66 | 'lattitude': lattitude, 67 | 'longitude': longitude, 68 | 'mobileImei': mobileImei, 69 | 'caseList': caseList, 70 | 'nic': nic, 71 | 'passport': passport, 72 | 'country': country, 73 | 'age': age, 74 | 'gender': gender, 75 | }; 76 | return map; 77 | } 78 | 79 | static Registration fromMap(Map map) { 80 | if (map == null) return null; 81 | 82 | return Registration( 83 | name: map['name'], 84 | email: map['email'], 85 | address: map['address'], 86 | lattitude: map['lattitude'], 87 | longitude: map['longitude'], 88 | mobileImei: map['mobileImei'], 89 | caseList: List.from(map['caseList']), 90 | nic: map['nic'], 91 | passport: map['passport'], 92 | country: map['country'], 93 | age: map['age'], 94 | gender: map['gender'], 95 | ); 96 | } 97 | 98 | String toJson() => json.encode(toMap()); 99 | 100 | static Registration fromJson(String source) => fromMap(json.decode(source)); 101 | 102 | @override 103 | String toString() { 104 | return 'Registration(name: $name, email: $email, address: $address, lattitude: $lattitude, longitude: $longitude, mobileImei: $mobileImei, caseList: $caseList, nic: $nic, passport: $passport, country: $country, age: $age, gender: $gender)'; 105 | } 106 | 107 | @override 108 | bool operator ==(Object o) { 109 | if (identical(this, o)) return true; 110 | 111 | return o is Registration && 112 | o.name == name && 113 | o.email == email && 114 | o.address == address && 115 | o.lattitude == lattitude && 116 | o.longitude == longitude && 117 | o.mobileImei == mobileImei && 118 | o.caseList == caseList && 119 | o.nic == nic && 120 | o.passport == passport && 121 | o.country == country && 122 | o.age == age && 123 | o.gender == gender; 124 | } 125 | 126 | @override 127 | int get hashCode { 128 | return name.hashCode ^ 129 | email.hashCode ^ 130 | address.hashCode ^ 131 | lattitude.hashCode ^ 132 | longitude.hashCode ^ 133 | mobileImei.hashCode ^ 134 | caseList.hashCode ^ 135 | nic.hashCode ^ 136 | passport.hashCode ^ 137 | country.hashCode ^ 138 | age.hashCode ^ 139 | gender.hashCode; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /lib/models/reported_case.dart: -------------------------------------------------------------------------------- 1 | import 'package:equatable/equatable.dart'; 2 | import 'package:selftrackingapp/models/location.dart'; 3 | 4 | class ReportedCase extends Equatable { 5 | int id; 6 | String caseNumber; 7 | List locations; 8 | String message; 9 | DateTime createdAt; 10 | // New properties - need to be added to backend 11 | bool isLocal = true; 12 | bool isFromFacility = true; 13 | 14 | ReportedCase( 15 | {this.id, this.caseNumber, this.locations, this.message, this.createdAt}); 16 | 17 | factory ReportedCase.fromJson(Map json) { 18 | List _locations = []; 19 | // Replace with map 20 | json['locations'] 21 | .forEach((location) => _locations.add(Location.fromJson(location))); 22 | 23 | ReportedCase _case = ReportedCase( 24 | id: int.parse(json['id']), 25 | caseNumber: json['caseNumber'], 26 | locations: _locations, 27 | message: json['message'], 28 | createdAt: DateTime.parse(json['created'])); 29 | // isLocal 30 | if (json.containsKey('isLocal')) { 31 | _case.isLocal = json['isLocal'] as bool; 32 | } 33 | // Quarantine/home 34 | if (json.containsKey('detectedFrom')) { 35 | var from = json['detectedFrom'] as String; 36 | _case.isFromFacility = from == 'quarantine facility'; 37 | } 38 | // print("CASE HAS BEEN REPORTED: ${_case.id}"); 39 | return _case; 40 | } 41 | 42 | @override 43 | // TODO: implement props 44 | List get props => [id]; 45 | } 46 | -------------------------------------------------------------------------------- /lib/networking/api_client.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:convert'; 3 | 4 | import 'package:http/http.dart' as http; 5 | import 'package:selftrackingapp/constants.dart'; 6 | import 'package:selftrackingapp/models/news_article.dart'; 7 | import 'package:selftrackingapp/models/reported_case.dart'; 8 | import 'package:shared_preferences/shared_preferences.dart'; 9 | import 'package:flutter/foundation.dart'; 10 | 11 | import '../models/news_article.dart'; 12 | 13 | class ApiClient { 14 | // final String _baseUrl = 'https://api.covid-19.health.gov.lk'; 15 | final String _baseUrl; 16 | 17 | ApiClient() 18 | : _baseUrl = 19 | debugRelease ? testingServer : 'https://api.covid-19.health.gov.lk'; 20 | 21 | Future registerUser(u) async { 22 | final url = '$_baseUrl/user/register'; 23 | final response = await http.post(url); 24 | // Was this not a success? 25 | if (response.statusCode != 200) { 26 | print( 27 | 'Error registering user. Status: ' + response.statusCode.toString()); 28 | return false; 29 | } 30 | return true; 31 | } 32 | 33 | Future getLastMessageId() async { 34 | SharedPreferences prefs = await SharedPreferences.getInstance(); 35 | // int lastMessageId = prefs.getInt("last_message_id"); 36 | // if (lastMessageId == null) { 37 | // lastMessageId = 0; 38 | // } 39 | 40 | final url = '$_baseUrl/application/alert/latest'; 41 | print('Get last message ID: $url'); 42 | final response = await http.get(url); 43 | // Was this not a success? 44 | if (response.statusCode != 200) { 45 | print('Error getting latest message ID. Status: ' + 46 | response.statusCode.toString()); 47 | return -1; 48 | } 49 | int lastMessageServerId = jsonDecode(response.body) as int; 50 | // if (lastMessageId < lastMessageServerId) { 51 | // prefs.setInt("last_message_id", lastMessageServerId); 52 | var lastMessageId = lastMessageServerId; 53 | // } 54 | 55 | return lastMessageId; 56 | } 57 | 58 | Future> getArticleList(startId, endId, 59 | {forceUpdate = false}) async { 60 | //this will run everytime th user switchs tabs. 61 | List articles = []; 62 | // 63 | for (var i = startId; i <= endId; i++) { 64 | NewsArticle article = await getMessage(i, forceUpdate: forceUpdate); 65 | print("FETCHED ARTICLE: ${article.id}"); 66 | if (article != null) articles.add(article); 67 | } 68 | 69 | return articles; 70 | } 71 | 72 | Future getMessage(int id, {forceUpdate = false}) async { 73 | SharedPreferences prefs = await SharedPreferences.getInstance(); 74 | String lang = prefs.getString('preferred_language'); 75 | final sharedPrefId = "alert_$lang--$id"; 76 | print("Fetech id $sharedPrefId"); 77 | 78 | String alertData = prefs.getString(sharedPrefId); 79 | 80 | if (alertData == null || forceUpdate) { 81 | final url = '$_baseUrl/application/alert/$id/$lang'; 82 | final response = 83 | await http.get(url, headers: {'Content-Type': 'application/json'}); 84 | if (response.statusCode != 200) { 85 | print('Error getting message: $id. Status: ' + 86 | response.statusCode.toString()); 87 | return null; 88 | } 89 | alertData = utf8.decode(response.bodyBytes); 90 | prefs.setString(sharedPrefId, alertData); 91 | } 92 | 93 | // Create message 94 | var body = jsonDecode(alertData) as Map; 95 | 96 | NewsArticle article = NewsArticle.fromJSON(body); 97 | return article; 98 | } 99 | 100 | Future> getCaseList(startId, endId, 101 | {forceUpdate = false}) async { 102 | //this will run everytime th user switchs tabs. 103 | List articles = []; 104 | // 105 | for (var i = startId; i <= endId; i++) { 106 | ReportedCase article = await getCase(i, forceUpdate: forceUpdate); 107 | if (article != null) articles.add(article); 108 | } 109 | 110 | return articles; 111 | } 112 | 113 | Future getCase(int id, {forceUpdate = false}) async { 114 | SharedPreferences prefs = await SharedPreferences.getInstance(); 115 | String lang = prefs.getString('preferred_language'); 116 | final sharedPrefId = "case_$lang--$id"; 117 | 118 | String alertData = prefs.getString(sharedPrefId); 119 | 120 | if (alertData == null || forceUpdate) { 121 | final url = '$_baseUrl/application/case/$id/$lang'; 122 | print("Requesting data from $url"); 123 | final response = 124 | await http.get(url, headers: {'Content-Type': 'application/json'}); 125 | if (response.statusCode != 200) { 126 | print('Error getting message: $id. Status: ' + 127 | response.statusCode.toString()); 128 | return null; 129 | } 130 | alertData = utf8.decode(response.bodyBytes); 131 | prefs.setString(sharedPrefId, alertData); 132 | } 133 | 134 | // Create message 135 | var body = jsonDecode(alertData) as Map; 136 | ReportedCase article = ReportedCase.fromJson(body); 137 | 138 | return article; 139 | } 140 | 141 | Future getLastCaseId() async { 142 | SharedPreferences prefs = await SharedPreferences.getInstance(); 143 | int lastMessageId = 0; // prefs.getInt("last_case_id"); 144 | // if (lastMessageId == null) { 145 | // lastMessageId = 0; 146 | // } 147 | 148 | final url = '$_baseUrl/application/case/latest'; 149 | print('Get last message ID: $url'); 150 | final response = await http.get(url); 151 | // Was this not a success? 152 | if (response.statusCode != 200) { 153 | print('Error getting latest message ID. Status: ' + 154 | response.statusCode.toString()); 155 | return -1; 156 | } 157 | int lastMessageServerId = jsonDecode(response.body) as int; 158 | if (lastMessageId < lastMessageServerId) { 159 | prefs.setInt("last_case_id", lastMessageServerId); 160 | lastMessageId = lastMessageServerId; 161 | } 162 | 163 | return lastMessageId; 164 | } 165 | 166 | Future> getDashboardStatus() async { 167 | var result = Map(); 168 | final url = '$_baseUrl/application/dashboard/status'; 169 | // print('Get Dashboard status: $url'); 170 | final response = await http.get(url); 171 | // Was this not a success? 172 | if (response.statusCode != 200) { 173 | print('Error getting Dashboard status. Status: ' + 174 | response.statusCode.toString()); 175 | return result; 176 | } 177 | result = jsonDecode(response.body) as Map; 178 | // print('Dashboard info: $result'); 179 | return result; 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /lib/networking/data_repository.dart: -------------------------------------------------------------------------------- 1 | import 'package:selftrackingapp/exceptions/data_fetch_exception.dart'; 2 | import 'package:selftrackingapp/models/contact_us_contact.dart'; 3 | import 'package:selftrackingapp/models/news_article.dart'; 4 | import 'package:selftrackingapp/models/registration.dart'; 5 | import 'package:selftrackingapp/models/reported_case.dart'; 6 | import 'package:selftrackingapp/networking/db.dart'; 7 | 8 | abstract class DataRepository { 9 | Future> fetchCases(String lang); 10 | Future> fetchNewsArticles(); 11 | Future fetchCaseTotal(); 12 | Future> fetchContactUsContacts(); 13 | Future fetchPrivacyPolicy(); 14 | Future registerUser(Registration _cases); 15 | Future> fetchCountryList(); 16 | } 17 | 18 | class AppDataRepository implements DataRepository { 19 | final String TAG = "AppDataRepository: "; 20 | final DB _db; 21 | List _countries; 22 | 23 | AppDataRepository(this._db); 24 | 25 | @override 26 | Future> fetchCases(String lang) { 27 | try { 28 | return _db.fetchCases(lang); 29 | } catch (e) { 30 | throw DataFetchException(e); 31 | } 32 | } 33 | 34 | @override 35 | Future> fetchNewsArticles() { 36 | try { 37 | return _db 38 | .fetchNewsArticles(); //caching for news articles must also be implemented 39 | } catch (e) { 40 | throw DataFetchException(e); 41 | } 42 | } 43 | 44 | @override 45 | Future fetchCaseTotal() { 46 | try { 47 | return _db 48 | .fetchCaseTotal(); //caching for news articles must also be implemented 49 | } catch (e) { 50 | throw DataFetchException(e); 51 | } 52 | } 53 | 54 | @override 55 | Future> fetchContactUsContacts() { 56 | try { 57 | return _db 58 | .fetchContactUsContacts(); //caching for news articles must also be implemented 59 | } catch (e) { 60 | throw DataFetchException(e); 61 | } 62 | } 63 | 64 | @override 65 | Future fetchPrivacyPolicy() { 66 | try { 67 | return _db 68 | .fetchPrivacyPolicy(); //caching for news articles must also be implemented 69 | } catch (e) { 70 | throw DataFetchException(e); 71 | } 72 | } 73 | 74 | @override 75 | Future registerUser(Registration _cases) { 76 | print(_cases); 77 | try { 78 | return _db.registerUser( 79 | _cases); //caching for news articles must also be implemented 80 | } catch (e) { 81 | throw e; //passing exception to the UI 82 | } 83 | } 84 | 85 | @override 86 | Future> fetchCountryList() async { 87 | try { 88 | if (_countries == null) { 89 | _countries = await _db.fetchCountries(); 90 | return _countries; 91 | } 92 | return _countries; 93 | } catch (e) { 94 | throw e; //passing exception to the UI 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /lib/networking/db.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io'; 3 | import 'package:flutter/services.dart'; 4 | import 'package:http/http.dart'; 5 | import 'package:path_provider/path_provider.dart'; 6 | import 'package:selftrackingapp/exceptions/data_write_exception.dart'; 7 | import 'package:selftrackingapp/models/contact_us_contact.dart'; 8 | import 'package:logger/logger.dart'; 9 | import 'package:selftrackingapp/models/news_article.dart'; 10 | import 'package:selftrackingapp/models/registration.dart'; 11 | import 'package:selftrackingapp/models/reported_case.dart'; 12 | import 'package:http/http.dart' as http; 13 | import 'package:shared_preferences/shared_preferences.dart'; 14 | 15 | import '../constants.dart'; 16 | 17 | abstract class DB { 18 | Future> fetchCases(String lang); 19 | 20 | Future> fetchNewsArticles(); 21 | 22 | Future fetchCaseTotal(); 23 | 24 | Future fetchPrivacyPolicy(); 25 | 26 | Future> fetchContactUsContacts(); 27 | 28 | Future registerUser(Registration _cases); 29 | 30 | Future> fetchCountries(); 31 | } 32 | 33 | class AppDatabase implements DB { 34 | List articles = List(); 35 | 36 | final String _baseUrl; 37 | 38 | AppDatabase() 39 | : _baseUrl = 40 | debugRelease ? testingServer : 'https://api.covid-19.health.gov.lk'; 41 | 42 | @override 43 | Future> fetchCases(String lang) async { 44 | List _cases = []; 45 | 46 | http.Response response = 47 | await http.get('$_baseUrl/application/case/latest'); 48 | 49 | int casesLength = json.decode(response.body); 50 | 51 | for (int i = 1; i < casesLength + 1; i++) { 52 | http.Response res = await http.get('$_baseUrl/application/case/$i/$lang', 53 | headers: {'Content-Type': 'application/json'}); 54 | 55 | _cases.add(ReportedCase.fromJson(json.decode(res.body))); 56 | } 57 | 58 | return _cases; 59 | } 60 | 61 | @override 62 | Future> fetchNewsArticles() async { 63 | return await Future.delayed( 64 | const Duration(milliseconds: 2), () => articles); 65 | } 66 | 67 | @override 68 | Future fetchCaseTotal() async { 69 | return await Future.delayed(const Duration(milliseconds: 2), () => 125); 70 | } 71 | 72 | @override 73 | Future> fetchContactUsContacts() async { 74 | String jsonString = 75 | await rootBundle.loadString('assets/data/constant_data.json'); 76 | Map map = jsonDecode(jsonString); 77 | List contacts = List(); 78 | (map['contact_us_contacts'] as List).forEach((va) { 79 | contacts.add(ContactUsContact.fromJSON(va)); 80 | }); 81 | return contacts; 82 | } 83 | 84 | @override 85 | Future fetchPrivacyPolicy() async { 86 | String jsonString = 87 | await rootBundle.loadString('assets/data/constant_data.json'); 88 | Map map = jsonDecode(jsonString); 89 | 90 | return map['privacy_policy']; 91 | } 92 | 93 | @override 94 | Future registerUser( 95 | Registration registration, 96 | ) async { 97 | final url = '$_baseUrl/dhis/patients'; 98 | print("Registering the user.... $url"); 99 | print(registration.toJson()); 100 | String basicAuth = 'Basic ' + base64Encode(utf8.encode('admin:admin@123')); 101 | print(basicAuth); 102 | Response response = await http.post(url, 103 | body: registration.toJson(), 104 | headers: {"Content-Type": "application/json"}); 105 | if (response.statusCode == 200) { 106 | SharedPreferences prefs = await SharedPreferences.getInstance(); 107 | prefs.setString("register_id", utf8.decode(response.bodyBytes)); 108 | print("Registered User Successfully"); 109 | return; 110 | } else { 111 | print(response.body); 112 | throw DataWriteException( 113 | "Could not register user: ${response.statusCode}"); 114 | } 115 | } 116 | 117 | @override 118 | Future> fetchCountries() async { 119 | String jsonString = 120 | await rootBundle.loadString('assets/data/countries.json'); 121 | List jsonMap = jsonDecode(jsonString); 122 | List _countries = List(); 123 | jsonMap.forEach((listing) { 124 | _countries.add(listing["OptionCode"]); 125 | }); 126 | return _countries; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /lib/notifiers/registered_cases_model.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:selftrackingapp/models/reported_case.dart'; 3 | 4 | class RegisteredCasesModel extends ChangeNotifier { 5 | final List _reportedCases = []; 6 | 7 | /// An unmodifiable view of the items in the cart. 8 | List get reportedCases => _reportedCases; 9 | 10 | void add(ReportedCase reportedCase) { 11 | if (!_reportedCases.contains(reportedCase)) { 12 | _reportedCases.insert(0, reportedCase); 13 | notifyListeners(); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lib/notifiers/stories_model.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | import '../models/news_article.dart'; 4 | import '../models/news_article.dart'; 5 | 6 | class StoriesModel extends ChangeNotifier { 7 | final List _articles = []; 8 | 9 | /// An unmodifiable view of the items in the cart. 10 | List get articles => _articles; 11 | 12 | void add(NewsArticle article) { 13 | if (!_articles.contains(article)) { 14 | _articles.insert(0, article); 15 | notifyListeners(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/page/ios_faq.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../app_localizations.dart'; 3 | 4 | class IOSFAQScreen extends StatefulWidget { 5 | @override 6 | _IOSFAQScreenState createState() => _IOSFAQScreenState(); 7 | } 8 | 9 | class _IOSFAQScreenState extends State { 10 | @override 11 | Widget build(BuildContext context) { 12 | return Scaffold( 13 | appBar: AppBar( 14 | backgroundColor: Colors.white, 15 | iconTheme: IconThemeData(color: Colors.black), 16 | title: Text( 17 | AppLocalizations.of(context) 18 | .translate("popmenu_ios_faq"), 19 | style: TextStyle( 20 | color: Colors.black, 21 | fontWeight: FontWeight.bold, 22 | fontSize: 20.0, 23 | ), 24 | ), 25 | ), 26 | body: Center( 27 | child: Text("iOS FAQ"), 28 | ), 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/page/screen/case_details_screen.dart: -------------------------------------------------------------------------------- 1 | // import 'dart:async'; 2 | // import 'dart:convert'; 3 | // import 'dart:typed_data'; 4 | // import 'package:geolocator/geolocator.dart'; 5 | // import 'package:intl/intl.dart'; 6 | // import 'dart:ui' as ui; 7 | 8 | // import 'package:flutter/material.dart'; 9 | // import 'package:flutter/services.dart'; 10 | // import 'package:google_maps_flutter/google_maps_flutter.dart'; 11 | // import 'package:selftrackingapp/models/location.dart'; 12 | // import 'package:selftrackingapp/widgets/custom_text.dart'; 13 | 14 | // DateFormat dateFormat = DateFormat("yyyy-MM-dd HH:mm:ss"); 15 | 16 | // class CaseDetailScreen extends StatefulWidget { 17 | // @override 18 | // State createState() => CaseDetailScreenState(); 19 | // } 20 | 21 | // class CaseDetailScreenState extends State { 22 | // static const MethodChannel _channel = MethodChannel('location'); 23 | 24 | // Completer _controller = Completer(); 25 | 26 | // Position currentLocation; 27 | // List entries = List(); 28 | // List hospitalLocations = List(); 29 | // Timer _locationTimer; 30 | 31 | // Timer _currentLoctimer; 32 | // bool _isInitialLocationAdded = false; 33 | 34 | // Future updateLocation() async { 35 | // List newEntries = await getLocationUpdate(); 36 | // print("LOCATIONS Fetched: ${newEntries.length}"); 37 | // if (this.mounted) { 38 | // setState(() { 39 | // // entries.clear(); 40 | // newEntries.forEach((e) { 41 | // if (!entries.contains(e)) { 42 | // entries.add(e); 43 | // //location id should be used here to prevent duplicate locations from being added 44 | // } 45 | // }); 46 | // print("POLLED locations: ${newEntries.length}"); 47 | // }); 48 | // } 49 | // } 50 | 51 | // Future getBytesFromAsset(String path, int width) async { 52 | // ByteData data = await rootBundle.load(path); 53 | // ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List(), 54 | // targetWidth: width); 55 | // ui.FrameInfo fi = await codec.getNextFrame(); 56 | // return (await fi.image.toByteData(format: ui.ImageByteFormat.png)) 57 | // .buffer 58 | // .asUint8List(); 59 | // } 60 | 61 | // @override 62 | // void initState() { 63 | // super.initState(); 64 | // updateLocation(); 65 | 66 | // parseJsonFromAssets("assets/hospitals.json").then((data) async { 67 | // final Uint8List markerIcon = 68 | // await getBytesFromAsset('assets/images/hospital_sign_map.png', 100); 69 | 70 | // for (var h in data["hospitals"]) { 71 | // setState(() { 72 | // hospitalLocations.add(Marker( 73 | // icon: BitmapDescriptor.fromBytes(markerIcon), 74 | // markerId: MarkerId("${h["id"]}_id"), 75 | // infoWindow: InfoWindow(title: "${h["name"]}"), 76 | // position: LatLng(h["lon"], h["lat"]))); 77 | // }); 78 | // } 79 | // }); 80 | 81 | // WidgetsBinding.instance.addPostFrameCallback((_) { 82 | // _channel.invokeMethod('requestLocationPermission').then((res) { 83 | // _channel.invokeMethod('openLocationService').then((res) {}); 84 | // }); 85 | 86 | // _locationTimer = Timer.periodic(Duration(minutes: 5), (timer) async { 87 | // print("POLLING the locations"); 88 | // await updateLocation(); 89 | // }); 90 | 91 | // _currentLoctimer = Timer.periodic(Duration(seconds: 2), (_) { 92 | // Geolocator() 93 | // .getCurrentPosition(desiredAccuracy: LocationAccuracy.best) 94 | // .then((position) { 95 | // if (this.mounted) { 96 | // setState(() { 97 | // if (!_isInitialLocationAdded) { 98 | // Location location = new Location( 99 | // longitude: position.longitude, 100 | // latitude: position.latitude, 101 | // date: position.timestamp, 102 | // from: position.timestamp, 103 | // to: position.timestamp, 104 | // address: 'Current Location'); 105 | // _isInitialLocationAdded = true; 106 | // entries.add(location); 107 | // moveMapToCurrentLoc(); 108 | // } 109 | // currentLocation = position; 110 | // }); 111 | // } 112 | // }); 113 | // print("Current Location Updated"); 114 | // }); 115 | // }); 116 | // } 117 | 118 | // Future> parseJsonFromAssets(String assetsPath) async { 119 | // print('--- Parse json from: $assetsPath'); 120 | // return rootBundle 121 | // .loadString(assetsPath) 122 | // .then((jsonStr) => jsonDecode(jsonStr)); 123 | // } 124 | 125 | // void moveMapToCurrentLoc() async { 126 | // final GoogleMapController controller = await _controller.future; 127 | // final CameraPosition _camPos = CameraPosition( 128 | // zoom: 15.0, 129 | // target: LatLng(currentLocation.latitude, currentLocation.longitude)); 130 | // controller.animateCamera(CameraUpdate.newCameraPosition(_camPos)); 131 | // } 132 | 133 | // @override 134 | // void dispose() { 135 | // super.dispose(); 136 | // if (_locationTimer != null) _locationTimer.cancel(); 137 | // if (_currentLoctimer != null) _currentLoctimer.cancel(); 138 | // print("CANCELLING timers"); 139 | // } 140 | 141 | // @override 142 | // Widget build(BuildContext context) { 143 | // return Container( 144 | // child: getMapView(entries), //initially this will be empty 145 | // ); 146 | // } 147 | 148 | // Widget getMapView(List entries) { 149 | // return GoogleMap( 150 | // mapType: MapType.normal, 151 | // markers: hospitalLocations.toSet(), 152 | // circles: entries.map((l) { 153 | // return Circle( 154 | // circleId: CircleId("${l.date.millisecondsSinceEpoch}"), 155 | // fillColor: Colors.blue.withOpacity(0.2), 156 | // strokeColor: Colors.blue, 157 | // strokeWidth: 1, 158 | // center: LatLng(l.latitude, l.longitude), 159 | // radius: 150, 160 | // consumeTapEvents: true, 161 | // onTap: () { 162 | // _showDialog(l); 163 | // }); 164 | // }).toSet(), 165 | // initialCameraPosition: CameraPosition( 166 | // target: currentLocation != null 167 | // ? LatLng(currentLocation.latitude, currentLocation.longitude) 168 | // : LatLng(6.9271, 79.8612), 169 | // zoom: 12, 170 | // ), 171 | // myLocationButtonEnabled: true, 172 | // trafficEnabled: true, 173 | // // myLocationEnabled: true, 174 | // onMapCreated: (GoogleMapController controller) { 175 | // _controller.complete(controller); 176 | // }, 177 | // ); 178 | // } 179 | 180 | // void _showDialog(Location location) { 181 | // // flutter defined function 182 | // showDialog( 183 | // context: context, 184 | // builder: (BuildContext context) { 185 | // // return object of type Dialog 186 | // return AlertDialog( 187 | // title: new Text("Your location"), 188 | // content: 189 | // new Text("You were here at ${dateFormat.format(location.date)}"), 190 | // actions: [ 191 | // // usually buttons at the bottom of the dialog 192 | // new FlatButton( 193 | // child: new Text("Close"), 194 | // onPressed: () { 195 | // Navigator.of(context).pop(); 196 | // }, 197 | // ), 198 | // ], 199 | // ); 200 | // }, 201 | // ); 202 | // } 203 | 204 | // Widget getListView(List entries) { 205 | // return ListView.builder( 206 | // padding: const EdgeInsets.all(8), 207 | // itemCount: entries.length, 208 | // itemBuilder: (BuildContext context, int index) { 209 | // return Text( 210 | // 'Entry ${entries[index].longitude},${entries[index].latitude},${entries[index].date}'); 211 | // }); 212 | // } 213 | 214 | // Future> getLocationUpdate() async { 215 | // try { 216 | // final List locations = 217 | // await _channel.invokeMethod('getLocation'); 218 | // print("locations $locations"); 219 | 220 | // return locations 221 | // .map((v) => Location.fromBackgroundJson(json.decode(v))) 222 | // .toList(); 223 | // } on Exception catch (e) { 224 | // print(e); 225 | // } 226 | // return null; 227 | // } 228 | // } 229 | -------------------------------------------------------------------------------- /lib/page/screen/component/news_component.dart: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICTASL/MyHealthApp/146fa269e5f280d72c571146f0a6d9c8b114d1b1/lib/page/screen/component/news_component.dart -------------------------------------------------------------------------------- /lib/page/screen/faq_screen.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:selftrackingapp/widgets/custom_text.dart'; 5 | 6 | import '../../app_localizations.dart'; 7 | 8 | class FAQScreenContent extends StatelessWidget { 9 | @override 10 | Widget build(BuildContext context) { 11 | final jsonStr = AppLocalizations.of(context).translate("faq"); 12 | Map faq = JsonCodec().decode(jsonStr); 13 | return Container( 14 | child: ListView.builder( 15 | itemBuilder: (context, index) { 16 | final key = faq.keys.elementAt(index); 17 | String value = faq.values.elementAt(index); 18 | return Padding( 19 | padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 5), 20 | child: Card( 21 | elevation: 3, 22 | child: ListTile( 23 | title: Container( 24 | margin: EdgeInsets.only(top: 12, bottom: 0), 25 | child: Text( 26 | key, 27 | style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), 28 | ), 29 | ), 30 | subtitle: Container( 31 | margin: EdgeInsets.symmetric(vertical: 15), 32 | child: Text( 33 | value, 34 | style: TextStyle(fontSize: 15, fontStyle: FontStyle.italic), 35 | ), 36 | ), 37 | ), 38 | ), 39 | ); 40 | }, 41 | itemCount: faq.length, 42 | ), 43 | ); 44 | } 45 | } 46 | 47 | class FAQScreen extends StatelessWidget { 48 | @override 49 | Widget build(BuildContext context) { 50 | return Scaffold( 51 | appBar: AppBar( 52 | backgroundColor: Colors.white, 53 | iconTheme: IconThemeData(color: Colors.black), 54 | title: Text( 55 | AppLocalizations.of(context).translate("popmenu_faq"), 56 | style: TextStyle( 57 | color: Colors.black, 58 | fontWeight: FontWeight.bold, 59 | fontSize: 20.0, 60 | ), 61 | ), 62 | ), 63 | body: FAQScreenContent(), 64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /lib/page/screen/news_detail_screen.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:cached_network_image/cached_network_image.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter_html/flutter_html.dart'; 6 | import 'package:flutter_html/rich_text_parser.dart'; 7 | import 'package:selftrackingapp/models/message_type.dart'; 8 | import 'package:selftrackingapp/models/news_article.dart'; 9 | import 'package:selftrackingapp/networking/api_client.dart'; 10 | import 'package:selftrackingapp/theme.dart'; 11 | import 'package:selftrackingapp/widgets/custom_text.dart'; 12 | import 'package:share/share.dart'; 13 | import 'package:url_launcher/url_launcher.dart'; 14 | import 'package:webview_flutter/webview_flutter.dart'; 15 | 16 | import '../../app_localizations.dart'; 17 | 18 | import 'package:intl/intl.dart'; 19 | 20 | DateFormat dateFormat = DateFormat("dd-MM-yy HH:mm"); 21 | 22 | class NewsDetailScreen extends StatefulWidget { 23 | final NewsArticle article; 24 | 25 | const NewsDetailScreen({Key key, this.article}) : super(key: key); 26 | 27 | @override 28 | _NewsDetailScreenState createState() => _NewsDetailScreenState(); 29 | } 30 | 31 | class _NewsDetailScreenState extends State { 32 | @override 33 | void initState() { 34 | super.initState(); 35 | print(widget.article.message); 36 | } 37 | 38 | void _shareArticle(NewsArticle article) { 39 | Share.share("${article.title}\n" 40 | "${article.subtitle}\n" 41 | "by ${article.originator}\n" 42 | "${dateFormat.format(article.created)}\n"); 43 | } 44 | 45 | Widget _buildTitle() { 46 | return Column( 47 | crossAxisAlignment: CrossAxisAlignment.start, 48 | children: [ 49 | Column( 50 | mainAxisAlignment: MainAxisAlignment.start, 51 | crossAxisAlignment: CrossAxisAlignment.start, 52 | children: [ 53 | Row( 54 | children: [ 55 | Expanded( 56 | child: Text( 57 | widget.article.title, 58 | textAlign: TextAlign.start, 59 | style: Theme.of(context).textTheme.title.copyWith( 60 | fontWeight: FontWeight.bold, 61 | ), 62 | ), 63 | ), 64 | ], 65 | ), 66 | SizedBox( 67 | height: 5, 68 | ), 69 | Row( 70 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 71 | children: [ 72 | Text( 73 | "By ${widget.article.originator}", 74 | textAlign: TextAlign.start, 75 | style: 76 | Theme.of(context).textTheme.body1.copyWith(fontSize: 12), 77 | ), 78 | Spacer(), 79 | Text( 80 | "${dateFormat.format(widget.article.created)}", 81 | //published data needs to facilitated into the messages from the API 82 | style: 83 | Theme.of(context).textTheme.body1.copyWith(fontSize: 12), 84 | ), 85 | ], 86 | ), 87 | ], 88 | ) 89 | ], 90 | ); 91 | } 92 | 93 | @override 94 | Widget build(BuildContext context) { 95 | Icon _icon = Icon( 96 | Icons.info, 97 | color: Colors.blue, 98 | ); 99 | 100 | switch (widget.article.messageType) { 101 | case MessageType.Critical: 102 | _icon = Icon( 103 | Icons.report, 104 | color: Colors.red, 105 | size: 30.0, 106 | ); 107 | break; 108 | case MessageType.Warning: 109 | _icon = Icon( 110 | Icons.warning, 111 | color: Colors.amber, 112 | size: 30.0, 113 | ); 114 | break; 115 | case MessageType.Info: 116 | _icon = Icon( 117 | Icons.info, 118 | color: Colors.blue, 119 | size: 30.0, 120 | ); 121 | break; 122 | } 123 | 124 | return Scaffold( 125 | backgroundColor: Colors.white, 126 | appBar: AppBar( 127 | backgroundColor: Colors.white, 128 | iconTheme: IconThemeData(color: Colors.black), 129 | title: Text( 130 | widget.article.title, 131 | style: TextStyle(color: Colors.black), 132 | ), 133 | actions: [ 134 | IconButton( 135 | onPressed: () { 136 | _shareArticle(widget.article); 137 | }, 138 | icon: Icon( 139 | Icons.share, 140 | color: Colors.blue, 141 | ), 142 | ) 143 | ], 144 | ), 145 | body: Container( 146 | child: Padding( 147 | padding: const EdgeInsets.all(0.0), 148 | child: Container( 149 | child: Padding( 150 | padding: const EdgeInsets.all(16.0), 151 | child: Column( 152 | children: [ 153 | _buildTitle(), 154 | SizedBox( 155 | height: 30.0, 156 | ), 157 | Divider(), 158 | Expanded( 159 | child: WebView( 160 | initialUrl: Uri.dataFromString( 161 | widget.article.message, 162 | mimeType: 'text/html', 163 | encoding: Encoding.getByName('utf-8')) 164 | .toString(), 165 | navigationDelegate: 166 | (NavigationRequest request) async { 167 | if (await canLaunch(request.url)) { 168 | await launch(request.url); 169 | } else { 170 | print("Cannot launch url"); 171 | } 172 | return NavigationDecision.prevent; 173 | }, 174 | javascriptMode: JavascriptMode.unrestricted, 175 | ), 176 | ), 177 | ], 178 | ), 179 | ), 180 | )))); 181 | } 182 | 183 | // var testhtml = 184 | // "
\n

What is Lorem Ipsum?

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Why do we use it?

It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here',

  1. one
  2. two
  3. three

\n
"; 185 | 186 | } 187 | -------------------------------------------------------------------------------- /lib/page/screen/pharamacy_list_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:selftrackingapp/utils/tracker_colors.dart'; 3 | import 'package:selftrackingapp/widgets/custom_text.dart'; 4 | import 'package:url_launcher/url_launcher.dart'; 5 | import 'package:webview_flutter/webview_flutter.dart'; 6 | 7 | import '../../app_localizations.dart'; 8 | 9 | class PharmacyScreen extends StatelessWidget { 10 | @override 11 | Widget build(BuildContext context) { 12 | return Scaffold( 13 | body: Padding( 14 | padding: const EdgeInsets.all(8.0), 15 | child: Container( 16 | decoration: BoxDecoration( 17 | color: Colors.white, 18 | borderRadius: BorderRadius.all(Radius.circular(20.0))), 19 | padding: const EdgeInsets.all(20.0), 20 | child: Row( 21 | mainAxisSize: MainAxisSize.max, 22 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 23 | children: [ 24 | Container( 25 | constraints: BoxConstraints( 26 | maxWidth: MediaQuery.of(context).size.width / 2), 27 | child: Column( 28 | mainAxisSize: MainAxisSize.min, 29 | crossAxisAlignment: CrossAxisAlignment.start, 30 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 31 | children: [ 32 | Text( 33 | AppLocalizations.of(context).translate("pharmacy_list"), 34 | style: TextStyle( 35 | fontSize: 20.0, 36 | color: Colors.black, 37 | fontWeight: FontWeight.bold, 38 | ), 39 | textAlign: TextAlign.start, 40 | ), 41 | SizedBox(height: 5.0), 42 | ], 43 | ), 44 | ), 45 | Container( 46 | child: GestureDetector( 47 | onTap: () async { 48 | var link = "https://pharmacy.health.gov.lk/"; 49 | if (await canLaunch(link)) { 50 | await launch(link); 51 | } 52 | }, 53 | child: Container( 54 | decoration: BoxDecoration( 55 | shape: BoxShape.circle, 56 | color: TrackerColors.primaryColor, 57 | ), 58 | padding: EdgeInsets.all(15.0), 59 | child: Icon(Icons.web, color: Colors.white))), 60 | ), 61 | ], 62 | ), 63 | ), 64 | )); 65 | } 66 | } 67 | 68 | //Container( 69 | // child: FutureBuilder( 70 | // future: GetIt.instance().fetchPrivacyPolicy(), 71 | // builder: (context, snapshot) { 72 | // switch (snapshot.connectionState) { 73 | // case ConnectionState.none: 74 | // return Center( 75 | // child: 76 | // Text("Failed getting privacy policy, try again later"), 77 | // ); 78 | // break; 79 | // case ConnectionState.waiting: 80 | // return Center( 81 | // child: CircularProgressIndicator(), 82 | // ); 83 | // break; 84 | // case ConnectionState.active: 85 | // return Center( 86 | // child: 87 | // Text("Failed getting privacy policy, try again later"), 88 | // ); 89 | // break; 90 | // case ConnectionState.done: 91 | // return Container( 92 | // padding: const EdgeInsets.all(20.0), 93 | // child: Text(snapshot.data), 94 | // ); 95 | // break; 96 | // } 97 | // }, 98 | // ), 99 | // ) 100 | -------------------------------------------------------------------------------- /lib/page/screen/privacy_policy_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:selftrackingapp/widgets/custom_text.dart'; 3 | import 'package:webview_flutter/webview_flutter.dart'; 4 | 5 | import '../../app_localizations.dart'; 6 | 7 | class PrivacyPolicyScreen extends StatelessWidget { 8 | @override 9 | Widget build(BuildContext context) { 10 | return Scaffold( 11 | appBar: AppBar( 12 | backgroundColor: Colors.white, 13 | iconTheme: IconThemeData(color: Colors.black), 14 | title: Text( 15 | AppLocalizations.of(context).translate("popmenu_privpolicy"), 16 | style: TextStyle(color: Colors.black), 17 | ), 18 | ), 19 | body: WebView( 20 | initialUrl: 21 | "https://test.covid-19.health.gov.lk/documents/privacy-policy", 22 | javascriptMode: JavascriptMode.unrestricted, 23 | )); 24 | } 25 | } 26 | 27 | //Container( 28 | // child: FutureBuilder( 29 | // future: GetIt.instance().fetchPrivacyPolicy(), 30 | // builder: (context, snapshot) { 31 | // switch (snapshot.connectionState) { 32 | // case ConnectionState.none: 33 | // return Center( 34 | // child: 35 | // Text("Failed getting privacy policy, try again later"), 36 | // ); 37 | // break; 38 | // case ConnectionState.waiting: 39 | // return Center( 40 | // child: CircularProgressIndicator(), 41 | // ); 42 | // break; 43 | // case ConnectionState.active: 44 | // return Center( 45 | // child: 46 | // Text("Failed getting privacy policy, try again later"), 47 | // ); 48 | // break; 49 | // case ConnectionState.done: 50 | // return Container( 51 | // padding: const EdgeInsets.all(20.0), 52 | // child: Text(snapshot.data), 53 | // ); 54 | // break; 55 | // } 56 | // }, 57 | // ), 58 | // ) 59 | -------------------------------------------------------------------------------- /lib/page/screen/qr_scan_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:qr_code_scanner/qr_code_scanner.dart'; 3 | import 'package:selftrackingapp/page/screen/qr_webview_screen.dart'; 4 | import 'package:webview_flutter/webview_flutter.dart'; 5 | 6 | import '../../app_localizations.dart'; 7 | 8 | class QrScanScreen extends StatefulWidget { 9 | @override 10 | _QrScanScreenState createState() => _QrScanScreenState(); 11 | } 12 | 13 | class _QrScanScreenState extends State { 14 | final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); 15 | var qrText = ""; 16 | QRViewController controller; 17 | bool scanned = false; 18 | @override 19 | void initState() { 20 | super.initState(); 21 | } 22 | 23 | @override 24 | void dispose() { 25 | controller?.dispose(); 26 | super.dispose(); 27 | } 28 | 29 | @override 30 | Widget build(BuildContext context) { 31 | double height = MediaQuery.of(context).size.height; 32 | return scanned == false 33 | ? Scaffold( 34 | body: Column( 35 | children: [ 36 | Expanded( 37 | flex: 5, 38 | child: QRView( 39 | key: qrKey, 40 | onQRViewCreated: _onQRViewCreated, 41 | ), 42 | ), 43 | Row( 44 | children: [ 45 | Container( 46 | padding: EdgeInsets.all(10), 47 | height: 100, 48 | width: 100, 49 | color: Colors.white, 50 | child: Image.asset( 51 | "assets/images/stay_safe.png", 52 | fit: BoxFit.cover, 53 | ), 54 | ), 55 | Expanded( 56 | child: Center( 57 | child: Text( 58 | AppLocalizations.of(context).translate("qr_instruct"), 59 | overflow: TextOverflow.ellipsis, 60 | maxLines: 2, 61 | style: TextStyle(color: Colors.black, fontSize: 20), 62 | ), 63 | ), 64 | ) 65 | ], 66 | ) 67 | ], 68 | ), 69 | ) 70 | : Container(); 71 | } 72 | 73 | void _handleURLButtonPress(BuildContext context, String url) { 74 | // Navigator.push(context, 75 | // MaterialPageRoute(builder: (context) => QrWebviewScreen(url: url))) 76 | // .then((_) { 77 | // _backagain(); 78 | // }); 79 | 80 | Navigator.push(context, 81 | MaterialPageRoute(builder: (context) => QrWebviewScreen(url: url))) 82 | .then((_) { 83 | _backagain(); 84 | }); 85 | } 86 | 87 | void _backagain() { 88 | setState(() { 89 | scanned = false; 90 | controller.resumeCamera(); 91 | }); 92 | } 93 | 94 | void _onQRViewCreated(QRViewController controller) { 95 | this.controller = controller; 96 | 97 | controller.scannedDataStream.listen((scanData) { 98 | if (scanned == false) { 99 | setState(() { 100 | qrText = scanData; 101 | if (qrText != "") { 102 | scanned = true; 103 | 104 | controller.pauseCamera(); 105 | _handleURLButtonPress(context, qrText); 106 | } 107 | }); 108 | } 109 | }); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /lib/page/screen/qr_webview_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:qr_code_scanner/qr_code_scanner.dart'; 3 | import 'package:selftrackingapp/main.dart'; 4 | import 'package:selftrackingapp/page/screen/privacy_policy_screen.dart'; 5 | import 'package:selftrackingapp/page/screen/root_screen.dart'; 6 | import 'package:selftrackingapp/page/screen/welcome_screen.dart'; 7 | import 'package:url_launcher/url_launcher.dart'; 8 | import 'package:webview_flutter/webview_flutter.dart'; 9 | 10 | import '../../app_localizations.dart'; 11 | import 'qr_scan_screen.dart'; 12 | 13 | class QrWebviewScreen extends StatefulWidget { 14 | final String url; 15 | 16 | const QrWebviewScreen({Key key, this.url}) : super(key: key); 17 | @override 18 | _QrWebviewScreenState createState() => _QrWebviewScreenState(); 19 | } 20 | 21 | WebViewController controllerGlobal; 22 | 23 | class _QrWebviewScreenState extends State { 24 | @override 25 | void initState() { 26 | super.initState(); 27 | } 28 | 29 | @override 30 | Widget build(BuildContext context) { 31 | return Scaffold( 32 | appBar: AppBar( 33 | backgroundColor: Colors.white, 34 | leading: IconButton( 35 | icon: Icon(Icons.arrow_back), 36 | onPressed: () { 37 | Navigator.of(context) 38 | .push(MaterialPageRoute(builder: (_) => HomeScreen())); 39 | }), 40 | iconTheme: IconThemeData(color: Colors.black), 41 | title: Text( 42 | AppLocalizations.of(context).translate("qr_title"), 43 | style: TextStyle(color: Colors.black), 44 | ), 45 | ), 46 | body: WebView( 47 | initialUrl: widget.url, 48 | // navigationDelegate: (NavigationRequest request) async { 49 | // if (await canLaunch(request.url)) { 50 | // await launch(request.url); 51 | // } else { 52 | // print("Cannot launch url"); 53 | // } 54 | // return NavigationDecision.prevent; 55 | // }, 56 | javascriptMode: JavascriptMode.unrestricted, 57 | )); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /lib/page/screen/selected_case_detail_screen.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:convert'; 3 | import 'package:geolocator/geolocator.dart'; 4 | import 'package:intl/intl.dart'; 5 | 6 | import 'package:flutter/material.dart'; 7 | import 'package:flutter/services.dart'; 8 | import 'package:google_maps_flutter/google_maps_flutter.dart'; 9 | import 'package:selftrackingapp/models/location.dart'; 10 | import 'package:selftrackingapp/models/reported_case.dart'; 11 | 12 | DateFormat dateFormat = DateFormat("yyyy-MM-dd HH:mm:ss"); 13 | 14 | class SelectedCaseDetailScreen extends StatefulWidget { 15 | final ReportedCase reportedCase; 16 | 17 | const SelectedCaseDetailScreen({Key key, this.reportedCase}) 18 | : super(key: key); 19 | 20 | @override 21 | _SelectedCaseDetailScreenState createState() => 22 | _SelectedCaseDetailScreenState(); 23 | } 24 | 25 | class _SelectedCaseDetailScreenState extends State { 26 | static const MethodChannel _channel = MethodChannel('location'); 27 | 28 | Completer _controller = Completer(); 29 | Position _currentLocation; 30 | 31 | List locationMarkers = []; 32 | 33 | @override 34 | void initState() { 35 | super.initState(); 36 | 37 | // initializing _currentLocation with first location of the reported case 38 | try { 39 | _currentLocation = Position( 40 | latitude: widget.reportedCase.locations[0].latitude, 41 | longitude: widget.reportedCase.locations[0].longitude); 42 | } catch (e) { 43 | print(e); 44 | } 45 | 46 | // http://localhost:8000/application/dhis/patients 47 | 48 | BitmapDescriptor.fromAssetImage( 49 | ImageConfiguration(devicePixelRatio: 0.1, size: Size(0.5, 0.5)), 50 | "assets/images/user_icon.png") 51 | .then((userIcon) { 52 | BitmapDescriptor.fromAssetImage( 53 | ImageConfiguration(devicePixelRatio: 0.1, size: Size(0.5, 0.5)), 54 | "assets/images/suspected_icon.png") 55 | .then((suspectIcon) { 56 | getLocationUpdate().then((List locations) { 57 | setState(() { 58 | locationMarkers = widget.reportedCase.locations.map((l) { 59 | return Marker( 60 | icon: suspectIcon, 61 | alpha: 0.5, 62 | infoWindow: InfoWindow( 63 | title: 64 | "Suspected person is at ${dateFormat.format(l.date)}", 65 | snippet: ""), 66 | markerId: MarkerId("${l.date.millisecondsSinceEpoch}"), 67 | position: LatLng(l.latitude, l.longitude)); 68 | }).toList(); 69 | 70 | // locationMarkers.addAll(locations.map((l) { 71 | // return Marker( 72 | // icon: userIcon, 73 | // alpha: 0.5, 74 | // infoWindow: InfoWindow( 75 | // title: "You where there at ${dateFormat.format(l.date)}", 76 | // snippet: ""), 77 | // markerId: MarkerId("${l.date.millisecondsSinceEpoch}"), 78 | // position: LatLng(l.latitude, l.longitude)); 79 | // }).toList(growable: false)); 80 | }); 81 | }); 82 | }); 83 | }); 84 | } 85 | 86 | @override 87 | void dispose() { 88 | super.dispose(); 89 | // if (_locationTimer != null) _locationTimer.cancel(); 90 | // if (_currentLoctimer != null) _currentLoctimer.cancel(); 91 | print("CANCELLING timers"); 92 | } 93 | 94 | @override 95 | Widget build(BuildContext context) { 96 | return Container( 97 | child: getMapView( 98 | widget.reportedCase.locations), //initially this will be empty 99 | ); 100 | } 101 | 102 | Widget getMapView(List entries) { 103 | return Scaffold( 104 | appBar: AppBar( 105 | backgroundColor: Colors.white, 106 | iconTheme: IconThemeData(color: Colors.black), 107 | title: Text("${widget.reportedCase.caseNumber}", 108 | style: TextStyle(color: Colors.black)), 109 | ), 110 | body: GoogleMap( 111 | mapType: MapType.terrain, 112 | markers: getMapEntries(), 113 | circles: widget.reportedCase.locations.map((l) { 114 | return Circle( 115 | circleId: CircleId("${l.date.millisecondsSinceEpoch}"), 116 | center: LatLng(l.latitude, l.longitude), 117 | radius: 50, 118 | fillColor: Colors.red.withOpacity(0.5), 119 | strokeColor: Colors.transparent, 120 | strokeWidth: 0); 121 | }).toSet(), 122 | initialCameraPosition: CameraPosition( 123 | target: _currentLocation != null 124 | ? LatLng(_currentLocation.latitude, _currentLocation.longitude) 125 | : LatLng(6.9271, 79.8612), 126 | zoom: 12, 127 | ), 128 | myLocationButtonEnabled: true, 129 | myLocationEnabled: true, 130 | onMapCreated: (GoogleMapController controller) { 131 | _controller.complete(controller); 132 | }, 133 | ), 134 | ); 135 | } 136 | 137 | Widget getListView(List entries) { 138 | return ListView.builder( 139 | padding: const EdgeInsets.all(8), 140 | itemCount: entries.length, 141 | itemBuilder: (BuildContext context, int index) { 142 | return Text( 143 | 'Entry ${entries[index].longitude},${entries[index].latitude},${entries[index].date}'); 144 | }); 145 | } 146 | 147 | Future> getLocationUpdate() async { 148 | try { 149 | final List locations = 150 | await _channel.invokeMethod('getLocation'); 151 | print("locations $locations"); 152 | 153 | return locations 154 | .map((v) => Location.fromBackgroundJson(json.decode(v))) 155 | .toList(); 156 | } on Exception catch (e) { 157 | print(e); 158 | } 159 | return null; 160 | } 161 | 162 | getMapEntries() { 163 | return locationMarkers.toSet(); 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /lib/theme.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | const primaryColor = Color(0xFF615ed8); 4 | const primaryColorText = Color(0xFF242424); 5 | const secondaryColorText = Color(0xFF615ed8); 6 | const lightColorText = Color(0xFFFFFFFF); 7 | 8 | const primaryColorSwitch = Color(0xFF615ed8); 9 | const colorBackground = Color(0xFF242424); 10 | const colorAccentBackground = Color(0xFFFFFFFF); 11 | const colorBackgroundItemBorder = Color(0xFF707070); 12 | const colorDefaultCardBackground = Color(0xFF615ed8); 13 | const colorOne = Color(0xFF951288); 14 | 15 | var backgroundShadowColor = Colors.black.withOpacity(0.48); 16 | 17 | var titleBackgroundColor = colorOne; 18 | 19 | const textColor = Color(0xFFFFFFFF); 20 | const textLinkColor = Colors.white; 21 | const textUnderLineColor = Color(0xFFFFFFFF); 22 | const textSecondColor = Color(0xFFf9f871); 23 | 24 | const defaultButtonColor = Color(0xFFff8e6f); 25 | const defaultButtonTextColor = Color(0xFFFFFFFF); 26 | 27 | const warningButtonColor = Color(0xFFEF7801); 28 | const warningButtonTextColor = Color(0xFFFFFFFF); 29 | const warningButtonFlipTextColor = Color(0xFFEF7801); 30 | 31 | const mainButtonColor = Color(0xFFE849F3); 32 | const mainButtonTextColor = Color(0xFFFFFFFF); 33 | 34 | const successButtonColor = Color(0xFF7C28C7); 35 | const successButtonTextColor = Color(0xFFFFFFFF); 36 | const successButtonFlipTextColor = Color(0xFF7C28C7); 37 | 38 | // Text StyleElement 39 | const h1TextStyle = TextStyle(fontSize: 34.0, color: textColor); 40 | const h2TextStyle = TextStyle(fontSize: 24.0, color: textColor); 41 | const h3TextStyle = TextStyle(fontSize: 20.0, color: textColor); 42 | const h4TextStyle = TextStyle(fontSize: 18.0, color: textColor); 43 | const h5TextStyle = TextStyle(fontSize: 16.0, color: textColor); 44 | const h6TextStyle = TextStyle(fontSize: 14.0, color: textColor); 45 | 46 | var linkButtonTextStyle = h5TextStyle.copyWith(color: Colors.white); 47 | 48 | var backgroundTextShadow = Shadow( 49 | blurRadius: 10.0, 50 | color: backgroundShadowColor, 51 | offset: Offset(5.0, 10.0), 52 | ); 53 | var backgroundBoxShadow = BoxShadow( 54 | blurRadius: 10.0, 55 | color: backgroundShadowColor, 56 | offset: Offset(5.0, 10.0), 57 | ); 58 | -------------------------------------------------------------------------------- /lib/utils/tracker_colors.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class TrackerColors { 4 | static int secondaryColor = 0xffDAD2D8; 5 | static MaterialColor primaryColor = MaterialColor(0xFF311F4C, { 6 | 50: Color.fromRGBO(0x31, 0x1F, 0x4C, .1), 7 | 100: Color.fromRGBO(0x31, 0x1F, 0x4C, .2), 8 | 200: Color.fromRGBO(0x31, 0x1F, 0x4C, .3), 9 | 300: Color.fromRGBO(0x31, 0x1F, 0x4C, .4), 10 | 400: Color.fromRGBO(0x31, 0x1F, 0x4C, .5), 11 | 500: Color.fromRGBO(0x31, 0x1F, 0x4C, .6), 12 | 600: Color.fromRGBO(0x31, 0x1F, 0x4C, .7), 13 | 700: Color.fromRGBO(0x31, 0x1F, 0x4C, .8), 14 | 800: Color.fromRGBO(0x31, 0x1F, 0x4C, .9), 15 | 900: Color.fromRGBO(0x31, 0x1F, 0x4C, 1), 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /lib/widgets/animated_tracker_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../utils/tracker_colors.dart'; 4 | 5 | class AnimatedTrackerButton extends StatelessWidget { 6 | const AnimatedTrackerButton( 7 | {this.height = 100, 8 | this.width = 30, 9 | this.child, 10 | this.onPressed, 11 | this.active = true}); 12 | 13 | final double height; 14 | final double width; 15 | final Widget child; 16 | final Function() onPressed; 17 | final bool active; 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | assert(child != null); 22 | if (active) assert(onPressed != null); 23 | return RaisedButton( 24 | shape: 25 | RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)), 26 | padding: const EdgeInsets.all(20.0), 27 | onPressed: active ? onPressed : () {}, 28 | child: AnimatedContainer( 29 | duration: Duration(milliseconds: 200), 30 | curve: Curves.easeIn, 31 | height: height, 32 | width: width, 33 | child: Center( 34 | child: AnimatedSwitcher( 35 | switchInCurve: Curves.easeIn, 36 | duration: Duration(milliseconds: 200), 37 | child: child, 38 | )), 39 | ), 40 | color: TrackerColors.primaryColor); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/widgets/custom_text.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ffi'; 2 | 3 | import 'package:auto_size_text/auto_size_text.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:selftrackingapp/app_localizations.dart'; 6 | 7 | class CustomText extends StatelessWidget { 8 | final String data; 9 | final TextAlign textAlign; 10 | final TextStyle style; 11 | final bool isChangeFontSize; 12 | 13 | CustomText(this.data, 14 | {this.textAlign, this.style, this.isChangeFontSize = true}); 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | TextStyle style = this.style; 19 | 20 | var locale = AppLocalizations.of(context).locale; 21 | if (locale.languageCode == "ta" && this.isChangeFontSize && style != null) { 22 | double fontSize = style.fontSize != null ? style.fontSize * 75 / 100 : 14; 23 | style = style.copyWith(fontSize: fontSize); 24 | } 25 | 26 | return AutoSizeText( 27 | data, 28 | textAlign: textAlign, 29 | style: style, 30 | maxLines: 2, 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/widgets/language_select.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:selftrackingapp/theme.dart'; 3 | 4 | class LanguageSelectWidget extends StatefulWidget { 5 | final Function(String language) notifyLanguageChange; 6 | 7 | const LanguageSelectWidget({Key key, this.notifyLanguageChange}) 8 | : super(key: key); 9 | 10 | @override 11 | _LanguageSelectWidgetState createState() => _LanguageSelectWidgetState(); 12 | } 13 | 14 | class _LanguageSelectWidgetState extends State { 15 | String dropdownValue = "English"; 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | return DropdownButton( 20 | value: dropdownValue, 21 | icon: Icon( 22 | Icons.language, 23 | color: Colors.white, 24 | ), 25 | iconSize: 24, 26 | elevation: 16, 27 | style: TextStyle(color: Colors.white, fontSize: 18) 28 | .copyWith(fontWeight: FontWeight.w500), 29 | onChanged: (String newValue) { 30 | setState(() { 31 | dropdownValue = newValue; 32 | widget.notifyLanguageChange(newValue); 33 | }); 34 | }, 35 | focusColor: Colors.red, 36 | items: ['Sinhala', 'Tamil', 'English'] 37 | .map>((String value) { 38 | return DropdownMenuItem( 39 | value: value, 40 | child: Text( 41 | value, 42 | style: h4TextStyle.copyWith(color: Colors.white), 43 | ), 44 | ); 45 | }).toList(), 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /local.properties: -------------------------------------------------------------------------------- 1 | ## This file must *NOT* be checked into Version Control Systems, 2 | # as it contains information specific to your local configuration. 3 | # 4 | # Location of the SDK. This is only used by Gradle. 5 | # For customization when using a Version Control System, please read the 6 | # header note. 7 | #Sun Mar 15 13:22:50 IST 2020 8 | sdk.dir=C\:\\Users\\Dewmal\\Android 9 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: selftrackingapp 2 | description: Self tracking app 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # In Android, build-name is used as versionName while build-number used as versionCode. 10 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 11 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 12 | # Read more about iOS versioning at 13 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 14 | version: 1.17.2+39 15 | 16 | environment: 17 | sdk: ">=2.1.0 <3.0.0" 18 | 19 | dependencies: 20 | flutter: 21 | sdk: flutter 22 | get_it: ^4.0.0 23 | cached_network_image: ^2.0.0 24 | share: ^0.6.3+6 25 | firebase_messaging: ^6.0.13 26 | firebase_remote_config: ^0.3.0+3 27 | google_maps_flutter: ^0.5.21+3 28 | shared_preferences: ^0.5.6+3 29 | url_launcher: ^5.4.2 30 | http: ^0.12.0+4 31 | logger: ^0.8.3 32 | timeago: ^2.0.26 33 | google_fonts: ^0.3.9 34 | titled_navigation_bar: ^3.6.0 35 | date_format: ^1.0.8 36 | provider: ^4.0.4 37 | equatable: ^1.1.1 38 | geolocator: ^5.3.1 39 | async: ^2.4.0 40 | package_info: ^0.4.0+16 41 | connectivity: ^0.4.8+2 42 | dropdown_banner: ^1.4.0 43 | recursive_regex: ^0.1.3+2 44 | webview_flutter: ^0:3:19+9 45 | auto_size_text: ^2.1.0 46 | flutter_html: ^0.11.1 47 | flutter_colorpicker: ^0.3.4 48 | qr_code_scanner: ^0.0.12 49 | 50 | 51 | 52 | clustering_google_maps: ^0.1.2 53 | 54 | flutter_localizations: 55 | sdk: flutter 56 | 57 | # The following adds the Cupertino Icons font to your application. 58 | # Use with the CupertinoIcons class for iOS style icons. 59 | cupertino_icons: ^0.1.2 60 | 61 | dev_dependencies: 62 | flutter_test: 63 | sdk: flutter 64 | 65 | # For information on the generic Dart part of this file, see the 66 | # following page: https://dart.dev/tools/pub/pubspec 67 | 68 | # The following section is specific to Flutter. 69 | flutter: 70 | # The following line ensures that the Material Icons font is 71 | # included with your application, so that you can use the icons in 72 | # the material Icons class. 73 | uses-material-design: true 74 | 75 | # To add assets to your application, add an assets section, like this: 76 | assets: 77 | - assets/images/welcome_screen_bg.png 78 | - assets/images/bg.png 79 | - assets/lang/en.json 80 | - assets/lang/si.json 81 | - assets/lang/ta.json 82 | - assets/hospitals.json 83 | - assets/images/logo.png 84 | - assets/images/hospital_sign_map.png 85 | - assets/images/suspected_icon.png 86 | - assets/images/user_icon.png 87 | - assets/data/constant_data.json 88 | - assets/data/countries.json 89 | - assets/images/rehabilitation.svg 90 | - assets/images/suspect.svg 91 | - assets/images/locateme_24px.svg 92 | - assets/images/home_24px.svg 93 | - assets/images/death.svg 94 | - assets/images/contactus_24px.svg 95 | - assets/images/casefinder_24px.svg 96 | - assets/images/announcement_24px.svg 97 | - assets/images/ambulance.svg 98 | - assets/images/add_ic_call_24px.svg 99 | - assets/images/medical_consultion.png 100 | - assets/images/stay_safe.png 101 | 102 | # An image asset can refer to one or more resolution-specific "variants", see 103 | # https://flutter.dev/assets-and-images/#resolution-aware. 104 | # For details regarding adding assets from package dependencies, see 105 | # https://flutter.dev/assets-and-images/#from-packages 106 | # To add custom fonts to your application, add a fonts section here, 107 | # in this "flutter" section. Each entry in this list should have a 108 | # "family" key with the font family name, and a "fonts" key with a 109 | # list giving the asset and other descriptors for the font. For 110 | # example: 111 | # fonts: 112 | # - family: Schyler 113 | # fonts: 114 | # - asset: fonts/Schyler-Regular.ttf 115 | # - asset: fonts/Schyler-Italic.ttf 116 | # style: italic 117 | # - family: Trajan Pro 118 | # fonts: 119 | # - asset: fonts/TrajanPro.ttf 120 | # - asset: fonts/TrajanPro_Bold.ttf 121 | # weight: 700 122 | # 123 | # For details regarding fonts from package dependencies, 124 | # see https://flutter.dev/custom-fonts/#from-packages 125 | -------------------------------------------------------------------------------- /pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Purpose 2 | 3 | The purpose of this PR is to fix # 4 | 5 | ## Goals 6 | 7 | 8 | ## Approach 9 | 10 | 11 | ### Screenshots 12 | 13 | 14 | ## Checklist 15 | - [x] This PR doesn't commit any keys, passwords, tokens, usernames, or other secrets. 16 | - [ ] I have read and understood the development best practices guidelines 17 | - [ ] My code follows the style guidelines of this project 18 | - [ ] I have performed a self-review of my own code 19 | - [ ] I have commented my code, particularly in hard-to-understand areas 20 | - [ ] I have made corresponding changes to the documentation 21 | 22 | ## Related PRs 23 | 24 | 25 | ## Test environment 26 | 27 | 28 | ## Learning 29 | 30 | -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | void main() {} 9 | --------------------------------------------------------------------------------