├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── github-repo-stats.yml ├── .gitignore ├── .idea ├── .gitignore ├── .name ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── deploymentTargetDropDown.xml ├── deploymentTargetSelector.xml ├── gradle.xml ├── kotlinc.xml ├── migrations.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── vishal2376 │ │ └── gitcoach │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ ├── de │ │ │ ├── git_commands.json │ │ │ └── git_lessons.json │ │ ├── en │ │ │ ├── git_commands.json │ │ │ ├── git_lessons.json │ │ │ └── git_quiz.json │ │ ├── es │ │ │ ├── git_commands.json │ │ │ └── git_lessons.json │ │ ├── it │ │ │ ├── git_commands.json │ │ │ └── git_lessons.json │ │ ├── pt │ │ │ ├── git_commands.json │ │ │ └── git_lessons.json │ │ ├── ru │ │ │ ├── git_commands.json │ │ │ └── git_lessons.json │ │ ├── tr │ │ │ ├── git_commands.json │ │ │ └── git_lessons.json │ │ └── zh │ │ │ ├── git_commands.json │ │ │ ├── git_lessons.json │ │ │ └── git_quiz.json │ ├── ic_launcher-playstore.png │ ├── java │ │ └── com │ │ │ └── vishal2376 │ │ │ └── gitcoach │ │ │ ├── GitApplication.kt │ │ │ ├── MainActivity.kt │ │ │ ├── SplashScreen.kt │ │ │ ├── adapters │ │ │ ├── GitInfoAdapter.kt │ │ │ ├── GitLessonAdapter.kt │ │ │ ├── GitLessonStepAdapter.kt │ │ │ └── ViewPagerAdapter.kt │ │ │ ├── fragments │ │ │ ├── AboutUsFragment.kt │ │ │ ├── CommunityFragment.kt │ │ │ ├── ExploreFragment.kt │ │ │ ├── FontSettingFragment.kt │ │ │ ├── LearnFragment.kt │ │ │ ├── LessonFragment.kt │ │ │ ├── MainFragment.kt │ │ │ ├── QuizFragment.kt │ │ │ └── SettingsFragment.kt │ │ │ ├── models │ │ │ ├── GitCommand.kt │ │ │ ├── GitCommandItem.kt │ │ │ ├── lesson │ │ │ │ ├── GitLesson.kt │ │ │ │ ├── GitLessonItem.kt │ │ │ │ └── Step.kt │ │ │ └── quiz │ │ │ │ ├── GitQuiz.kt │ │ │ │ └── Quiz.kt │ │ │ └── utils │ │ │ ├── Category.kt │ │ │ ├── Constants.kt │ │ │ ├── LoadData.kt │ │ │ ├── LoadSettings.kt │ │ │ ├── LocaleHelper.kt │ │ │ └── Util.kt │ └── res │ │ ├── anim │ │ ├── alpha_anim.xml │ │ ├── bounce_anim.xml │ │ ├── popup_anim.xml │ │ ├── slide_down_anim.xml │ │ └── slide_up_anim.xml │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── app_logo.png │ │ ├── app_logo_svg.xml │ │ ├── box_round_border.xml │ │ ├── box_stroke_round_blue.xml │ │ ├── box_stroke_round_gray.xml │ │ ├── box_stroke_round_red.xml │ │ ├── bug_report.xml │ │ ├── circle.xml │ │ ├── developer.png │ │ ├── github.png │ │ ├── ic_check.xml │ │ ├── ic_code.xml │ │ ├── ic_developer.xml │ │ ├── ic_font_size.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_left_arrow.xml │ │ ├── ic_menu.xml │ │ ├── ic_more_apps.xml │ │ ├── ic_notification.xml │ │ ├── ic_palette.xml │ │ ├── ic_rate_start.xml │ │ ├── ic_search.xml │ │ ├── ic_share.xml │ │ ├── ic_suggestions.xml │ │ ├── ic_translate.xml │ │ ├── instagram.png │ │ ├── item_bg.xml │ │ ├── item_bg_green.xml │ │ ├── item_bg_red.xml │ │ ├── item_lesson_bg_unlocked.xml │ │ ├── line_circle.xml │ │ ├── linkedin.png │ │ ├── radio_bg_selector.xml │ │ ├── radio_correct_choice_bg.xml │ │ ├── round_bg_dark.xml │ │ └── twitter.png │ │ ├── font │ │ ├── roboto_medium.ttf │ │ └── rubik_medium.ttf │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── activity_splash_screen.xml │ │ ├── fragment_about_us.xml │ │ ├── fragment_community.xml │ │ ├── fragment_explore.xml │ │ ├── fragment_font_setting.xml │ │ ├── fragment_learn.xml │ │ ├── fragment_lesson.xml │ │ ├── fragment_main.xml │ │ ├── fragment_quiz.xml │ │ ├── fragment_settings.xml │ │ ├── git_info_item.xml │ │ ├── git_lesson_item.xml │ │ ├── git_lesson_step_item.xml │ │ └── nav_header.xml │ │ ├── menu │ │ └── nav_menu.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── navigation │ │ └── nav_graph.xml │ │ ├── values-de │ │ └── strings.xml │ │ ├── values-es │ │ └── strings.xml │ │ ├── values-it │ │ └── strings.xml │ │ ├── values-night │ │ ├── strings.xml │ │ └── themes.xml │ │ ├── values-pt │ │ └── strings.xml │ │ ├── values-ru │ │ └── strings.xml │ │ ├── values-tr │ │ └── strings.xml │ │ ├── values-zh │ │ └── strings.xml │ │ ├── values │ │ ├── arrays.xml │ │ ├── colors.xml │ │ ├── ic_launcher_background.xml │ │ ├── strings.xml │ │ ├── style.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ └── data_extraction_rules.xml │ └── test │ └── java │ └── com │ └── vishal2376 │ └── gitcoach │ └── ExampleUnitTest.kt ├── build.gradle ├── crowdin.yml ├── fastlane └── metadata │ └── android │ ├── de │ ├── full_description.txt │ └── short_description.txt │ └── en-US │ ├── changelogs │ └── 15.txt │ ├── full_description.txt │ ├── images │ ├── featureGraphic.jpg │ ├── icon.png │ └── phoneScreenshots │ │ ├── 01.jpg │ │ ├── 02.jpg │ │ ├── 03.jpg │ │ ├── 04.jpg │ │ ├── 05.jpg │ │ ├── 06.jpg │ │ ├── 07.jpg │ │ └── 08.jpg │ └── short_description.txt ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshots ├── about_us.jpg ├── cmdB.jpg ├── cmdG.jpg ├── cmdR.jpg ├── cmdY.jpg ├── font_settings.jpg ├── lesson.jpg ├── lesson_detail.jpg ├── nav.jpg ├── quiz.jpg ├── quiz_result.jpg └── search.jpg └── settings.gradle /.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/github-repo-stats.yml: -------------------------------------------------------------------------------- 1 | name: github-repo-stats 2 | 3 | on: 4 | schedule: 5 | # Run this once per day, towards the end of the day for keeping the most 6 | # recent data point most meaningful (hours are interpreted in UTC). 7 | - cron: "0 23 * * *" 8 | workflow_dispatch: # Allow for running this manually. 9 | 10 | jobs: 11 | j1: 12 | name: github-repo-stats 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: run-ghrs 16 | # Use latest release. 17 | uses: jgehrcke/github-repo-stats@RELEASE 18 | with: 19 | ghtoken: ${{ secrets.ghrs_github_api_token }} 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | /app/release 17 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | Git Coach -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 119 | 120 | 123 | 124 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/deploymentTargetDropDown.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/deploymentTargetSelector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/migrations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | 11 | 15 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 17 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 | # **Git+ Coach** 7 | 8 | Git+ Coach is a free education app designed to help users learn Git and its commands. With an easy-to-use interface and smooth animations, the app provides an enjoyable user experience without any ads to distract from the learning process. 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 |
21 | 22 | Get it on IzzyOnDroid 23 | Get it on Github 24 | 25 |
26 | 27 | ## Features 28 | - Browse through different categories of Git commands 29 | - Test your Git knowledge with Quiz 30 | - Search for any Git command 31 | - Font Size Customization 32 | - Copy Git command on single tap 33 | - Clear explanations and examples of each command 34 | - Smooth animations for a great user experience 35 | - Cool Themes: Blue,Green, Red, and Yellow 36 | - No ADS or In-App Subscription 37 | - Support 8 Languages (English,Chinese,German,Italian,Portuguese,Russian,Spanish,Turkish) 38 | 39 | ## Screenshots 40 | 41 | | | | | | 42 | |---|---|---|---| 43 | | | | | | 44 | | | | | | 45 | 46 | ## Getting Started 47 | 48 | To get started with Git+ Coach, simply download the app from the Google Play Store or download the source code and build it yourself. 49 | 50 | ### Prerequisites 51 | 52 | - Android Studio 53 | - Git 54 | 55 | ### Installing 56 | 57 | 1. Clone the repository 58 | ``` git clone https://github.com/vishal2376/git-coach.git ``` 59 | 2. Open the project in Android Studio 60 | 3. Build and run the app 61 | 62 | ## Contributing 63 | 64 | We welcome contributions from anyone interested in helping to improve Git+ Coach! Feel free to submit a pull request or open an issue if you notice any bugs or have suggestions for new features. 65 | 66 | 67 | ## Star History 68 | 69 | [![Star History Chart](https://api.star-history.com/svg?repos=vishal2376/git-coach&type=Timeline)](https://star-history.com/#vishal2376/git-coach&Timeline) 70 | 71 | ## License 72 | 73 | This project is licensed under the GPL v3.0 License - see the [LICENSE](LICENSE) file for details. 74 | 75 | ## Credits 76 | 77 | App Icon made by Freepik from www.flaticon.com 78 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'org.jetbrains.kotlin.android' 4 | id 'kotlin-kapt' 5 | id 'androidx.navigation.safeargs.kotlin' 6 | } 7 | 8 | android { 9 | namespace 'com.vishal2376.gitcoach' 10 | compileSdk 34 11 | 12 | kotlinOptions { jvmTarget = "17" } 13 | 14 | defaultConfig { 15 | applicationId "com.vishal2376.gitcoach" 16 | minSdk 24 17 | targetSdk 34 18 | versionCode 15 19 | versionName "5.2" 20 | 21 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 22 | } 23 | 24 | buildFeatures { 25 | viewBinding true 26 | } 27 | 28 | buildTypes { 29 | release { 30 | minifyEnabled false 31 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 32 | } 33 | } 34 | compileOptions { 35 | sourceCompatibility JavaVersion.VERSION_17 36 | targetCompatibility JavaVersion.VERSION_17 37 | } 38 | kotlinOptions { 39 | jvmTarget = JavaVersion.VERSION_17 40 | } 41 | } 42 | 43 | dependencies { 44 | 45 | implementation 'androidx.core:core-ktx:1.7.0' 46 | implementation 'androidx.appcompat:appcompat:1.6.0' 47 | implementation 'com.google.android.material:material:1.9.0' 48 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 49 | 50 | //ViewModal and livedata 51 | implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1' 52 | implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.1' 53 | 54 | //gson 55 | implementation 'com.google.code.gson:gson:2.9.0' 56 | 57 | //navigation 58 | implementation "androidx.navigation:navigation-fragment-ktx:2.6.0" 59 | implementation "androidx.navigation:navigation-ui-ktx:2.6.0" 60 | 61 | //scalable unit & text size 62 | implementation 'com.intuit.ssp:ssp-android:1.0.6' 63 | implementation 'com.intuit.sdp:sdp-android:1.0.6' 64 | 65 | //acra - crash reports 66 | def acraVersion = '5.10.1' 67 | implementation "ch.acra:acra-mail:$acraVersion" 68 | implementation "ch.acra:acra-dialog:$acraVersion" 69 | 70 | testImplementation 'junit:junit:4.13.2' 71 | androidTestImplementation 'androidx.test.ext:junit:1.1.5' 72 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' 73 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/vishal2376/gitcoach/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach 2 | 3 | import androidx.test.ext.junit.runners.AndroidJUnit4 4 | import androidx.test.platform.app.InstrumentationRegistry 5 | import org.junit.Assert.* 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | /** 10 | * Instrumented test, which will execute on an Android device. 11 | * 12 | * See [testing documentation](http://d.android.com/tools/testing). 13 | */ 14 | @RunWith(AndroidJUnit4::class) 15 | class ExampleInstrumentedTest { 16 | @Test 17 | fun useAppContext() { 18 | // Context of the app under test. 19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 20 | assertEquals("com.vishal2376.gitcoach", appContext.packageName) 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 15 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishal2376/git-coach/4d0411571b0b514136fb3714caa9ef808a9b4b54/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/GitApplication.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach 2 | 3 | import android.app.Application 4 | import android.content.Context 5 | import com.vishal2376.gitcoach.utils.Constants 6 | import org.acra.ACRA 7 | import org.acra.config.CoreConfigurationBuilder 8 | import org.acra.config.DialogConfigurationBuilder 9 | import org.acra.config.MailSenderConfigurationBuilder 10 | import org.acra.data.StringFormat 11 | 12 | 13 | class GitApplication : Application() { 14 | override fun attachBaseContext(base: Context?) { 15 | super.attachBaseContext(base) 16 | ACRA.init( 17 | this, CoreConfigurationBuilder() 18 | .withBuildConfigClass(BuildConfig::class.java) 19 | .withReportFormat(StringFormat.JSON) 20 | .withPluginConfigurations( 21 | 22 | // Dialog configuration: 23 | DialogConfigurationBuilder() 24 | .withText(getString(R.string.dialog_text)) 25 | .withTitle(getString(R.string.dialog_title)) 26 | .withPositiveButtonText(getString(R.string.dialog_positive)) 27 | .withNegativeButtonText(getString(R.string.dialog_negative)) 28 | .withResTheme(R.style.AppTheme_Dialog) 29 | .build(), 30 | 31 | // Mail sender configuration: 32 | MailSenderConfigurationBuilder() 33 | .withMailTo(Constants.email) 34 | .withReportFileName("crash_report.txt") 35 | .withReportAsFile(true) 36 | .build() 37 | ) 38 | ) 39 | } 40 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach 2 | 3 | import android.content.Intent 4 | import android.net.Uri 5 | import android.os.Bundle 6 | import android.widget.TextView 7 | import androidx.appcompat.app.AppCompatActivity 8 | import androidx.appcompat.app.AppCompatDelegate 9 | import androidx.constraintlayout.widget.ConstraintLayout 10 | import androidx.core.view.GravityCompat 11 | import androidx.navigation.fragment.NavHostFragment 12 | import com.vishal2376.gitcoach.databinding.ActivityMainBinding 13 | import com.vishal2376.gitcoach.utils.Constants 14 | import com.vishal2376.gitcoach.utils.Constants.shareMessage 15 | 16 | class MainActivity : AppCompatActivity() { 17 | 18 | private var _binding: ActivityMainBinding? = null 19 | private val binding get() = _binding!! 20 | 21 | override fun onCreate(savedInstanceState: Bundle?) { 22 | super.onCreate(savedInstanceState) 23 | 24 | // force dark mode 25 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) 26 | 27 | _binding = ActivityMainBinding.inflate(layoutInflater) 28 | setContentView(binding.root) 29 | 30 | appBarLayout = binding.appBarLayout 31 | 32 | //update app version in nav drawer 33 | val appVersion = binding.navView.getHeaderView(0).findViewById(R.id.tvAppVersion) 34 | appVersion.text = getString(R.string.app_version, BuildConfig.VERSION_NAME) 35 | 36 | binding.ivNavMenu.setOnClickListener { 37 | handleNavDrawer() 38 | } 39 | 40 | binding.navView.setNavigationItemSelectedListener { 41 | when (it.itemId) { 42 | R.id.itemReportBug -> { 43 | reportBug() 44 | } 45 | 46 | R.id.itemSuggestions -> { 47 | getSuggestions() 48 | } 49 | 50 | R.id.itemRateUs -> { 51 | rateUs() 52 | } 53 | 54 | R.id.itemShareApp -> { 55 | shareApp() 56 | } 57 | 58 | R.id.itemSourceCode -> { 59 | sourceCode() 60 | } 61 | 62 | R.id.itemMoreApps -> { 63 | moreApps() 64 | } 65 | 66 | R.id.itemDeveloper -> { 67 | developerProfile() 68 | } 69 | } 70 | true 71 | } 72 | 73 | binding.ivFontSize.setOnClickListener { 74 | val navHostFragment = 75 | supportFragmentManager.findFragmentById(R.id.fragmentContainerView) as NavHostFragment 76 | val navController = navHostFragment.navController 77 | navController.navigateUp() 78 | navController.navigate(R.id.fontSettingFragment) 79 | } 80 | 81 | binding.ivLanguage.setOnClickListener { 82 | val navHostFragment = 83 | supportFragmentManager.findFragmentById(R.id.fragmentContainerView) as NavHostFragment 84 | val navController = navHostFragment.navController 85 | navController.navigateUp() 86 | navController.navigate(R.id.settingsFragment) 87 | } 88 | 89 | } 90 | 91 | private fun handleNavDrawer() { 92 | binding.drawerLayout.openDrawer(GravityCompat.START) 93 | } 94 | 95 | private fun moreApps() { 96 | val intent = Intent( 97 | Intent.ACTION_VIEW, 98 | Uri.parse(Constants.GOOGLE_PLAY_DEV_LINK) 99 | ) 100 | startActivity(intent) 101 | 102 | } 103 | 104 | private fun shareApp() { 105 | val shareIntent = Intent(Intent.ACTION_SEND) 106 | shareIntent.type = "text/plain" 107 | shareMessage += "https://play.google.com/store/apps/details?id=" + applicationContext.packageName + "\n\n" 108 | shareIntent.putExtra(Intent.EXTRA_SUBJECT, "Git Coach") 109 | shareIntent.putExtra(Intent.EXTRA_TEXT, shareMessage) 110 | startActivity(Intent.createChooser(shareIntent, "Share This App")) 111 | } 112 | 113 | private fun reportBug() { 114 | val subject = "Git Coach: Report Bug" 115 | val uriBuilder = StringBuilder("mailto:" + Uri.encode(Constants.email)) 116 | uriBuilder.append("?subject=" + Uri.encode(subject)) 117 | val uriString = uriBuilder.toString() 118 | 119 | val intent = Intent(Intent.ACTION_SENDTO, Uri.parse(uriString)) 120 | startActivity(Intent.createChooser(intent, "Report Bug")) 121 | } 122 | 123 | private fun getSuggestions() { 124 | 125 | val subject = "Git Coach: Suggestions" 126 | val uriBuilder = StringBuilder("mailto:" + Uri.encode(Constants.email)) 127 | uriBuilder.append("?subject=" + Uri.encode(subject)) 128 | val uriString = uriBuilder.toString() 129 | 130 | val intent = Intent(Intent.ACTION_SENDTO, Uri.parse(uriString)) 131 | startActivity(Intent.createChooser(intent, "Send Suggestions")) 132 | } 133 | 134 | private fun rateUs() { 135 | val intent = Intent( 136 | Intent.ACTION_VIEW, 137 | Uri.parse("http://play.google.com/store/apps/details?id=" + applicationContext.packageName) 138 | ) 139 | startActivity(intent) 140 | 141 | } 142 | 143 | private fun sourceCode() { 144 | val intent = Intent( 145 | Intent.ACTION_VIEW, Uri.parse(Constants.SOURCE_CODE_LINK) 146 | ) 147 | startActivity(intent) 148 | 149 | } 150 | 151 | private fun developerProfile() { 152 | //close nav drawer 153 | binding.drawerLayout.close() 154 | 155 | //open about us page 156 | val navHostFragment = 157 | supportFragmentManager.findFragmentById(R.id.fragmentContainerView) as NavHostFragment 158 | val navController = navHostFragment.navController 159 | navController.navigateUp() 160 | navController.navigate(R.id.aboutUsFragment) 161 | } 162 | 163 | companion object { 164 | lateinit var appBarLayout: ConstraintLayout 165 | } 166 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/SplashScreen.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Intent 5 | import android.os.Bundle 6 | import android.os.Handler 7 | import android.os.Looper 8 | import android.view.animation.AnimationUtils 9 | import androidx.appcompat.app.AppCompatActivity 10 | import com.vishal2376.gitcoach.databinding.ActivitySplashScreenBinding 11 | import com.vishal2376.gitcoach.utils.LoadSettings 12 | 13 | @SuppressLint("CustomSplashScreen") 14 | class SplashScreen : AppCompatActivity() { 15 | 16 | private var _binding: ActivitySplashScreenBinding? = null 17 | private val binding get() = _binding!! 18 | override fun onCreate(savedInstanceState: Bundle?) { 19 | super.onCreate(savedInstanceState) 20 | 21 | //load settings 22 | LoadSettings.loadTheme(this) 23 | 24 | //set binding 25 | _binding = ActivitySplashScreenBinding.inflate(layoutInflater) 26 | setContentView(binding.root) 27 | 28 | //animation 29 | loadAnimation() 30 | 31 | //load main activity after some time 32 | Handler(Looper.getMainLooper()).postDelayed({ 33 | val intent = Intent(this, MainActivity::class.java) 34 | startActivity(intent) 35 | finish() 36 | }, 2000) 37 | 38 | } 39 | 40 | private fun loadAnimation() { 41 | val textAnim = AnimationUtils.loadAnimation(this, R.anim.slide_up_anim) 42 | binding.tvAppTitle.animation = textAnim 43 | 44 | val imgAnim = AnimationUtils.loadAnimation(this, R.anim.bounce_anim) 45 | binding.ivAppLogo.animation = imgAnim 46 | } 47 | 48 | override fun onDestroy() { 49 | super.onDestroy() 50 | _binding = null 51 | } 52 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/adapters/GitInfoAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.adapters 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.util.TypedValue 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import android.view.animation.AnimationUtils 10 | import android.widget.TextView 11 | import android.widget.Toast 12 | import androidx.recyclerview.widget.RecyclerView.Adapter 13 | import androidx.recyclerview.widget.RecyclerView.ViewHolder 14 | import com.vishal2376.gitcoach.R 15 | import com.vishal2376.gitcoach.models.GitCommandItem 16 | import com.vishal2376.gitcoach.utils.Category 17 | import com.vishal2376.gitcoach.utils.Constants 18 | import com.vishal2376.gitcoach.utils.LoadSettings 19 | import com.vishal2376.gitcoach.utils.copyToClipboard 20 | 21 | class GitInfoAdapter( 22 | private val context: Context, private var gitCommandList: List 23 | ) : Adapter() { 24 | 25 | private var titleSize: Float = Constants.FONT_SIZE_TITLE 26 | private var subTitleSize: Float = Constants.FONT_SIZE_SUB_TITLE 27 | private var descriptionSize: Float = Constants.FONT_SIZE_DESCRIPTION 28 | private var commandSize: Float = Constants.FONT_SIZE_COMMAND 29 | 30 | init { 31 | initFontSize() 32 | } 33 | 34 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GitInfoViewHolder { 35 | val view = 36 | LayoutInflater.from(parent.context).inflate(R.layout.git_info_item, parent, false) 37 | return GitInfoViewHolder(view) 38 | } 39 | 40 | override fun getItemCount(): Int { 41 | return gitCommandList.size 42 | } 43 | 44 | override fun onBindViewHolder(holder: GitInfoViewHolder, position: Int) { 45 | 46 | //set data 47 | val currentGitInfo = gitCommandList[position] 48 | holder.name.text = currentGitInfo.name 49 | holder.command.text = currentGitInfo.command 50 | holder.description.text = currentGitInfo.description 51 | holder.example.text = currentGitInfo.example 52 | 53 | //set font size 54 | holder.name.setTextSize(TypedValue.COMPLEX_UNIT_SP, titleSize) 55 | holder.exampleText.setTextSize(TypedValue.COMPLEX_UNIT_SP, subTitleSize) 56 | holder.description.setTextSize(TypedValue.COMPLEX_UNIT_SP, descriptionSize) 57 | holder.example.setTextSize(TypedValue.COMPLEX_UNIT_SP, descriptionSize) 58 | holder.command.setTextSize(TypedValue.COMPLEX_UNIT_SP, commandSize) 59 | 60 | //enable marquee effect 61 | holder.command.isSelected = true 62 | 63 | //copy to clipboard 64 | holder.command.setOnClickListener { 65 | copyToClipboard(context, holder.command.text.toString()) 66 | Toast.makeText(context, "Command Copied", Toast.LENGTH_SHORT).show() 67 | } 68 | 69 | //animation 70 | holder.itemView.animation = AnimationUtils.loadAnimation(context, R.anim.popup_anim) 71 | 72 | } 73 | 74 | @SuppressLint("NotifyDataSetChanged") 75 | fun setFilteredList(newList: List) { 76 | gitCommandList = newList 77 | notifyDataSetChanged() 78 | } 79 | 80 | inner class GitInfoViewHolder(itemView: View) : ViewHolder(itemView) { 81 | val name: TextView = itemView.findViewById(R.id.tvGitName) 82 | val command: TextView = itemView.findViewById(R.id.tvGitCommand) 83 | val description: TextView = itemView.findViewById(R.id.tvGitDescription) 84 | val example: TextView = itemView.findViewById(R.id.tvGitExample) 85 | val exampleText: TextView = itemView.findViewById(R.id.text_example) 86 | } 87 | 88 | private fun initFontSize() { 89 | //load font size from local 90 | val sliderTitleValue = LoadSettings.getFontSize(context, Category.FS_TITLE) 91 | val sliderDescriptionValue = LoadSettings.getFontSize(context, Category.FS_DESCRIPTION) 92 | val sliderCommandValue = LoadSettings.getFontSize(context, Category.FS_COMMAND) 93 | 94 | titleSize = Constants.FONT_SIZE_TITLE + sliderTitleValue 95 | subTitleSize = Constants.FONT_SIZE_SUB_TITLE + sliderDescriptionValue 96 | descriptionSize = Constants.FONT_SIZE_DESCRIPTION + sliderDescriptionValue 97 | commandSize = Constants.FONT_SIZE_COMMAND + sliderCommandValue 98 | } 99 | 100 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/adapters/GitLessonAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.adapters 2 | 3 | import android.content.Context 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import android.view.animation.AnimationUtils 8 | import android.widget.TextView 9 | import androidx.recyclerview.widget.RecyclerView.Adapter 10 | import androidx.recyclerview.widget.RecyclerView.ViewHolder 11 | import com.vishal2376.gitcoach.R 12 | import com.vishal2376.gitcoach.models.lesson.GitLessonItem 13 | 14 | class GitLessonAdapter( 15 | private val context: Context, 16 | private var gitLessonList: List, 17 | private val onLessonItemClicked: (Int) -> Unit 18 | ) : 19 | Adapter() { 20 | 21 | private var isLessonLock: Boolean = true 22 | 23 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GitLessonViewHolder { 24 | val view = 25 | LayoutInflater.from(parent.context).inflate(R.layout.git_lesson_item, parent, false) 26 | return GitLessonViewHolder(view) 27 | } 28 | 29 | override fun getItemCount(): Int { 30 | return gitLessonList.size 31 | } 32 | 33 | override fun onBindViewHolder(holder: GitLessonViewHolder, position: Int) { 34 | 35 | //set data 36 | val currentGitLesson = gitLessonList[position] 37 | holder.lessonCount.text = (position + 1).toString() 38 | holder.lessonTitle.text = currentGitLesson.LessonTitle 39 | 40 | //animation 41 | holder.itemView.animation = AnimationUtils.loadAnimation(context, R.anim.popup_anim) 42 | 43 | holder.itemView.setOnClickListener { 44 | onLessonItemClicked(position) 45 | } 46 | 47 | } 48 | 49 | inner class GitLessonViewHolder(itemView: View) : ViewHolder(itemView) { 50 | val lessonTitle: TextView = itemView.findViewById(R.id.tvLessonTitle) 51 | val lessonCount: TextView = itemView.findViewById(R.id.tvLessonCount) 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/adapters/GitLessonStepAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.adapters 2 | 3 | import android.content.Context 4 | import android.util.TypedValue 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import android.view.animation.AnimationUtils 9 | import android.widget.ImageView 10 | import android.widget.TextView 11 | import android.widget.Toast 12 | import androidx.recyclerview.widget.RecyclerView.Adapter 13 | import androidx.recyclerview.widget.RecyclerView.ViewHolder 14 | import com.vishal2376.gitcoach.R 15 | import com.vishal2376.gitcoach.models.lesson.GitLessonItem 16 | import com.vishal2376.gitcoach.utils.Category 17 | import com.vishal2376.gitcoach.utils.Constants 18 | import com.vishal2376.gitcoach.utils.LoadSettings 19 | import com.vishal2376.gitcoach.utils.copyToClipboard 20 | 21 | class GitLessonStepAdapter( 22 | private val context: Context, 23 | private var gitLesson: GitLessonItem 24 | ) : 25 | Adapter() { 26 | 27 | private var titleSize: Float = Constants.FONT_SIZE_TITLE 28 | private var descriptionSize: Float = Constants.FONT_SIZE_DESCRIPTION 29 | private var commandSize: Float = Constants.FONT_SIZE_COMMAND 30 | 31 | init { 32 | initFontSize() 33 | } 34 | 35 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GitLessonViewHolder { 36 | val view = 37 | LayoutInflater.from(parent.context) 38 | .inflate(R.layout.git_lesson_step_item, parent, false) 39 | return GitLessonViewHolder(view) 40 | } 41 | 42 | override fun getItemCount(): Int { 43 | return gitLesson.Steps.size 44 | } 45 | 46 | override fun onBindViewHolder(holder: GitLessonViewHolder, position: Int) { 47 | 48 | //set data 49 | val currentLessonStep = gitLesson.Steps[position] 50 | holder.lessonDescription.text = currentLessonStep.Description 51 | holder.lessonExplanation.text = currentLessonStep.Explanation 52 | 53 | //set font size 54 | holder.lessonDescription.setTextSize(TypedValue.COMPLEX_UNIT_SP, titleSize) 55 | holder.lessonExplanation.setTextSize(TypedValue.COMPLEX_UNIT_SP, descriptionSize) 56 | holder.lessonExample.setTextSize(TypedValue.COMPLEX_UNIT_SP, commandSize) 57 | 58 | 59 | if (currentLessonStep.Example.isEmpty()) 60 | holder.lessonExample.visibility = View.GONE 61 | else 62 | holder.lessonExample.text = currentLessonStep.Example 63 | 64 | //copy to clipboard 65 | holder.lessonExample.setOnClickListener { 66 | copyToClipboard(context, holder.lessonExample.text.toString()) 67 | Toast.makeText(context, "Command Copied", Toast.LENGTH_SHORT).show() 68 | } 69 | //hide vertical line of last element 70 | if (position == gitLesson.Steps.size - 1) 71 | holder.verticalLine.visibility = View.GONE 72 | 73 | //animation 74 | holder.itemView.animation = AnimationUtils.loadAnimation(context, R.anim.popup_anim) 75 | 76 | } 77 | 78 | inner class GitLessonViewHolder(itemView: View) : ViewHolder(itemView) { 79 | val lessonDescription: TextView = itemView.findViewById(R.id.tvLessonDescription) 80 | val lessonExplanation: TextView = itemView.findViewById(R.id.tvLessonExplanation) 81 | val lessonExample: TextView = itemView.findViewById(R.id.tvLessonExample) 82 | val verticalLine: ImageView = itemView.findViewById(R.id.ivVerticalLine) 83 | } 84 | 85 | private fun initFontSize() { 86 | //load font size from local 87 | val sliderTitleValue = LoadSettings.getFontSize(context, Category.FS_TITLE) 88 | val sliderDescriptionValue = LoadSettings.getFontSize(context, Category.FS_DESCRIPTION) 89 | val sliderCommandValue = LoadSettings.getFontSize(context, Category.FS_COMMAND) 90 | 91 | titleSize = Constants.FONT_SIZE_TITLE + sliderTitleValue 92 | descriptionSize = Constants.FONT_SIZE_DESCRIPTION + sliderDescriptionValue 93 | commandSize = Constants.FONT_SIZE_COMMAND + sliderCommandValue 94 | } 95 | 96 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/adapters/ViewPagerAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.adapters 2 | 3 | import androidx.fragment.app.Fragment 4 | import androidx.fragment.app.FragmentManager 5 | import androidx.lifecycle.Lifecycle 6 | import androidx.viewpager2.adapter.FragmentStateAdapter 7 | import com.vishal2376.gitcoach.fragments.CommunityFragment 8 | import com.vishal2376.gitcoach.fragments.ExploreFragment 9 | import com.vishal2376.gitcoach.fragments.LearnFragment 10 | 11 | class ViewPagerAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) : 12 | FragmentStateAdapter(fragmentManager, lifecycle) { 13 | 14 | override fun getItemCount(): Int { 15 | return 3 16 | } 17 | 18 | override fun createFragment(position: Int): Fragment { 19 | return when (position) { 20 | 0 -> { 21 | LearnFragment() 22 | } 23 | 24 | 1 -> { 25 | ExploreFragment() 26 | } 27 | 28 | 2 -> { 29 | CommunityFragment() 30 | } 31 | 32 | else -> { 33 | LearnFragment() 34 | } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/fragments/AboutUsFragment.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.fragments 2 | 3 | import android.content.Intent 4 | import android.net.Uri 5 | import android.os.Bundle 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import androidx.fragment.app.Fragment 10 | import androidx.navigation.fragment.findNavController 11 | import com.vishal2376.gitcoach.MainActivity 12 | import com.vishal2376.gitcoach.databinding.FragmentAboutUsBinding 13 | import com.vishal2376.gitcoach.utils.Constants 14 | 15 | class AboutUsFragment : Fragment() { 16 | 17 | private var _binding: FragmentAboutUsBinding? = null 18 | private val binding get() = _binding!! 19 | 20 | override fun onCreateView( 21 | inflater: LayoutInflater, container: ViewGroup?, 22 | savedInstanceState: Bundle? 23 | ): View { 24 | // Inflate the layout for this fragment 25 | _binding = FragmentAboutUsBinding.inflate(inflater, container, false) 26 | return binding.root 27 | } 28 | 29 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 30 | super.onViewCreated(view, savedInstanceState) 31 | 32 | handleButtons() 33 | } 34 | 35 | private fun handleButtons() { 36 | binding.tvAboutDeveloper.setOnClickListener { 37 | findNavController().popBackStack() 38 | } 39 | 40 | binding.apply { 41 | btnTwitter.setOnClickListener { 42 | openUrl(Constants.TWITTER_LINK) 43 | } 44 | btnGithub.setOnClickListener { 45 | openUrl(Constants.GITHUB_LINK) 46 | } 47 | btnInstagram.setOnClickListener { 48 | openUrl(Constants.INSTAGRAM_LINK) 49 | } 50 | btnLinkedin.setOnClickListener { 51 | openUrl(Constants.LINKEDIN_LINK) 52 | } 53 | } 54 | } 55 | 56 | private fun openUrl(url: String) { 57 | val intent = Intent( 58 | Intent.ACTION_VIEW, Uri.parse(url) 59 | ) 60 | startActivity(intent) 61 | } 62 | 63 | override fun onResume() { 64 | super.onResume() 65 | MainActivity.appBarLayout.visibility = View.GONE 66 | } 67 | 68 | override fun onDestroy() { 69 | super.onDestroy() 70 | MainActivity.appBarLayout.visibility = View.VISIBLE 71 | _binding = null 72 | } 73 | 74 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/fragments/CommunityFragment.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.fragments 2 | 3 | import android.content.Context.MODE_PRIVATE 4 | import android.os.Bundle 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import androidx.fragment.app.Fragment 9 | import androidx.navigation.fragment.findNavController 10 | import com.vishal2376.gitcoach.R 11 | import com.vishal2376.gitcoach.databinding.FragmentCommunityBinding 12 | import com.vishal2376.gitcoach.utils.Constants 13 | 14 | class CommunityFragment : Fragment() { 15 | 16 | private var _binding: FragmentCommunityBinding? = null 17 | private val binding get() = _binding!! 18 | 19 | private var correctAnswers = 0 20 | private var incorrectAnswers = 0 21 | 22 | override fun onCreateView( 23 | inflater: LayoutInflater, container: ViewGroup?, 24 | savedInstanceState: Bundle? 25 | ): View { 26 | 27 | // Inflate the layout for this fragment 28 | _binding = FragmentCommunityBinding.inflate(inflater, container, false) 29 | return binding.root 30 | } 31 | 32 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 33 | super.onViewCreated(view, savedInstanceState) 34 | 35 | initUI() 36 | handleButtons() 37 | 38 | } 39 | 40 | private fun initUI() { 41 | loadData() 42 | 43 | binding.apply { 44 | tvCorrectAnswers.text = correctAnswers.toString() 45 | tvIncorrectAnswers.text = incorrectAnswers.toString() 46 | } 47 | } 48 | 49 | private fun loadData() { 50 | correctAnswers = requireContext().getSharedPreferences("SETTINGS", MODE_PRIVATE) 51 | .getInt(Constants.CORRECT_ANSWERS, 0) 52 | incorrectAnswers = requireContext().getSharedPreferences("SETTINGS", MODE_PRIVATE) 53 | .getInt(Constants.INCORRECT_ANSWERS, 0) 54 | } 55 | 56 | private fun handleButtons() { 57 | binding.btnStartQuiz.setOnClickListener { 58 | findNavController().navigate(R.id.quizFragment) 59 | } 60 | } 61 | 62 | override fun onDestroyView() { 63 | super.onDestroyView() 64 | _binding = null 65 | } 66 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/fragments/ExploreFragment.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.fragments 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import android.widget.SearchView 8 | import androidx.fragment.app.Fragment 9 | import androidx.recyclerview.widget.LinearLayoutManager 10 | import com.vishal2376.gitcoach.adapters.GitInfoAdapter 11 | import com.vishal2376.gitcoach.databinding.FragmentExploreBinding 12 | import com.vishal2376.gitcoach.models.GitCommand 13 | import com.vishal2376.gitcoach.models.GitCommandItem 14 | import com.vishal2376.gitcoach.utils.LoadData 15 | import com.vishal2376.gitcoach.utils.LoadSettings 16 | import java.util.Locale 17 | 18 | class ExploreFragment : Fragment() { 19 | 20 | private var _binding: FragmentExploreBinding? = null 21 | private val binding get() = _binding!! 22 | 23 | private lateinit var gitInfoAdapter: GitInfoAdapter 24 | private lateinit var gitCommandList: GitCommand 25 | 26 | override fun onCreateView( 27 | inflater: LayoutInflater, container: ViewGroup?, 28 | savedInstanceState: Bundle? 29 | ): View { 30 | 31 | //load settings 32 | LoadSettings.loadTheme(requireContext()) 33 | 34 | // Inflate the layout for this fragment 35 | _binding = FragmentExploreBinding.inflate(inflater, container, false) 36 | 37 | return binding.root 38 | } 39 | 40 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 41 | super.onViewCreated(view, savedInstanceState) 42 | 43 | //get data 44 | gitCommandList = LoadData.getGitCommandData(requireContext())!! 45 | 46 | gitInfoAdapter = GitInfoAdapter(requireContext(), gitCommandList.gitCommands) 47 | 48 | //set recycler view 49 | binding.rvGitInfo.apply { 50 | setHasFixedSize(true) 51 | layoutManager = LinearLayoutManager(requireContext()) 52 | adapter = gitInfoAdapter 53 | } 54 | 55 | //search data 56 | binding.searchBar.setOnQueryTextListener(object : SearchView.OnQueryTextListener { 57 | override fun onQueryTextSubmit(query: String?): Boolean { 58 | return false 59 | } 60 | 61 | override fun onQueryTextChange(newText: String?): Boolean { 62 | filterList(newText) 63 | return true 64 | } 65 | 66 | }) 67 | 68 | } 69 | 70 | private fun filterList(query: String?) { 71 | if (query != null) { 72 | val filteredList = ArrayList() 73 | for (i in gitCommandList.gitCommands) { 74 | if (i.command.lowercase(Locale.ROOT).contains(query)) { 75 | filteredList.add(i) 76 | } 77 | } 78 | 79 | if (filteredList.isNotEmpty()) { 80 | gitInfoAdapter.setFilteredList(filteredList) 81 | } 82 | } 83 | } 84 | 85 | override fun onDestroyView() { 86 | super.onDestroyView() 87 | _binding = null 88 | } 89 | 90 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/fragments/FontSettingFragment.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.fragments 2 | 3 | import android.content.Context.MODE_PRIVATE 4 | import android.os.Bundle 5 | import android.util.TypedValue 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import android.view.animation.AnimationUtils 10 | import android.widget.Toast 11 | import androidx.fragment.app.Fragment 12 | import androidx.navigation.fragment.findNavController 13 | import com.vishal2376.gitcoach.MainActivity 14 | import com.vishal2376.gitcoach.R 15 | import com.vishal2376.gitcoach.databinding.FragmentFontSettingBinding 16 | import com.vishal2376.gitcoach.utils.Category 17 | import com.vishal2376.gitcoach.utils.Constants 18 | import com.vishal2376.gitcoach.utils.LoadSettings 19 | 20 | class FontSettingFragment : Fragment() { 21 | 22 | private var _binding: FragmentFontSettingBinding? = null 23 | private val binding get() = _binding!! 24 | 25 | private var titleSize: Float = Constants.FONT_SIZE_TITLE 26 | private var subTitleSize: Float = Constants.FONT_SIZE_SUB_TITLE 27 | private var descriptionSize: Float = Constants.FONT_SIZE_DESCRIPTION 28 | private var commandSize: Float = Constants.FONT_SIZE_COMMAND 29 | 30 | private var sliderTitleValue = 0f 31 | private var sliderDescriptionValue = 0f 32 | private var sliderCommandValue = 0f 33 | 34 | override fun onCreateView( 35 | inflater: LayoutInflater, container: ViewGroup?, 36 | savedInstanceState: Bundle? 37 | ): View { 38 | // Inflate the layout for this fragment 39 | _binding = FragmentFontSettingBinding.inflate(inflater, container, false) 40 | return binding.root 41 | } 42 | 43 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 44 | super.onViewCreated(view, savedInstanceState) 45 | 46 | initUI() 47 | handleInputs() 48 | handleButtons() 49 | 50 | } 51 | 52 | private fun initUI() { 53 | initFontSize() 54 | initAnimation() 55 | } 56 | 57 | private fun initAnimation() { 58 | binding.tvLessonTitle.animation = 59 | AnimationUtils.loadAnimation(requireContext(), R.anim.slide_down_anim) 60 | 61 | binding.layoutGitPreview.animation = 62 | AnimationUtils.loadAnimation(requireContext(), R.anim.alpha_anim) 63 | } 64 | 65 | private fun initFontSize() { 66 | //load font size from local 67 | sliderTitleValue = LoadSettings.getFontSize(requireContext(), Category.FS_TITLE) 68 | sliderDescriptionValue = LoadSettings.getFontSize(requireContext(), Category.FS_DESCRIPTION) 69 | sliderCommandValue = LoadSettings.getFontSize(requireContext(), Category.FS_COMMAND) 70 | 71 | //update sliders 72 | binding.sliderTitle.value = sliderTitleValue 73 | binding.sliderDescription.value = sliderDescriptionValue 74 | binding.sliderCommand.value = sliderCommandValue 75 | 76 | //update UI font 77 | titleSize = Constants.FONT_SIZE_TITLE + sliderTitleValue 78 | binding.tvGitName.setTextSize(TypedValue.COMPLEX_UNIT_SP, titleSize) 79 | 80 | subTitleSize = Constants.FONT_SIZE_SUB_TITLE + sliderDescriptionValue 81 | binding.textExample.setTextSize(TypedValue.COMPLEX_UNIT_SP, subTitleSize) 82 | 83 | descriptionSize = Constants.FONT_SIZE_DESCRIPTION + sliderDescriptionValue 84 | binding.tvGitDescription.setTextSize(TypedValue.COMPLEX_UNIT_SP, descriptionSize) 85 | binding.tvGitExample.setTextSize(TypedValue.COMPLEX_UNIT_SP, descriptionSize) 86 | 87 | commandSize = Constants.FONT_SIZE_COMMAND + sliderCommandValue 88 | binding.tvGitCommand.setTextSize(TypedValue.COMPLEX_UNIT_SP, commandSize) 89 | 90 | } 91 | 92 | private fun handleButtons() { 93 | binding.btnReset.setOnClickListener { 94 | binding.apply { 95 | sliderTitle.value = 0f 96 | sliderDescription.value = 0f 97 | sliderCommand.value = 0f 98 | } 99 | } 100 | 101 | binding.tvLessonTitle.setOnClickListener { 102 | findNavController().popBackStack() 103 | } 104 | 105 | binding.btnSave.setOnClickListener { 106 | val sharedPreferences = 107 | requireContext().getSharedPreferences("SETTINGS", MODE_PRIVATE) 108 | val editor = sharedPreferences.edit() 109 | editor.apply { 110 | putFloat(Category.FS_TITLE, binding.sliderTitle.value) 111 | putFloat(Category.FS_DESCRIPTION, binding.sliderDescription.value) 112 | putFloat(Category.FS_COMMAND, binding.sliderCommand.value) 113 | }.apply() 114 | 115 | Toast.makeText(requireContext(), "Font Setting Saved", Toast.LENGTH_SHORT).show() 116 | findNavController().popBackStack() 117 | } 118 | } 119 | 120 | private fun handleInputs() { 121 | binding.sliderTitle.addOnChangeListener { _, value, _ -> 122 | titleSize = Constants.FONT_SIZE_TITLE + value 123 | binding.tvGitName.setTextSize(TypedValue.COMPLEX_UNIT_SP, titleSize) 124 | } 125 | binding.sliderDescription.addOnChangeListener { _, value, _ -> 126 | subTitleSize = Constants.FONT_SIZE_SUB_TITLE + value 127 | binding.textExample.setTextSize(TypedValue.COMPLEX_UNIT_SP, subTitleSize) 128 | 129 | descriptionSize = Constants.FONT_SIZE_DESCRIPTION + value 130 | binding.tvGitDescription.setTextSize(TypedValue.COMPLEX_UNIT_SP, descriptionSize) 131 | binding.tvGitExample.setTextSize(TypedValue.COMPLEX_UNIT_SP, descriptionSize) 132 | } 133 | binding.sliderCommand.addOnChangeListener { _, value, _ -> 134 | commandSize = Constants.FONT_SIZE_COMMAND + value 135 | binding.tvGitCommand.setTextSize(TypedValue.COMPLEX_UNIT_SP, commandSize) 136 | } 137 | } 138 | 139 | override fun onResume() { 140 | super.onResume() 141 | MainActivity.appBarLayout.visibility = View.GONE 142 | } 143 | 144 | override fun onDestroy() { 145 | super.onDestroy() 146 | MainActivity.appBarLayout.visibility = View.VISIBLE 147 | _binding = null 148 | } 149 | 150 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/fragments/LearnFragment.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.fragments 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Bundle 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import androidx.fragment.app.Fragment 9 | import androidx.navigation.fragment.findNavController 10 | import androidx.recyclerview.widget.GridLayoutManager 11 | import com.vishal2376.gitcoach.adapters.GitLessonAdapter 12 | import com.vishal2376.gitcoach.databinding.FragmentLearnBinding 13 | import com.vishal2376.gitcoach.models.lesson.GitLesson 14 | import com.vishal2376.gitcoach.utils.LoadData 15 | import com.vishal2376.gitcoach.utils.LoadSettings 16 | 17 | class LearnFragment : Fragment() { 18 | 19 | private var _binding: FragmentLearnBinding? = null 20 | private val binding get() = _binding!! 21 | 22 | private lateinit var gitLessonAdapter: GitLessonAdapter 23 | private lateinit var gitLessonList: GitLesson 24 | 25 | override fun onCreateView( 26 | 27 | inflater: LayoutInflater, container: ViewGroup?, 28 | savedInstanceState: Bundle? 29 | ): View { 30 | 31 | //load settings 32 | LoadSettings.loadTheme(requireContext()) 33 | 34 | // Inflate the layout for this fragment 35 | _binding = FragmentLearnBinding.inflate(inflater, container, false) 36 | 37 | return binding.root 38 | } 39 | 40 | @SuppressLint("SetTextI18n") 41 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 42 | super.onViewCreated(view, savedInstanceState) 43 | 44 | //get json data 45 | gitLessonList = LoadData.getGitLessonData(requireContext())!! 46 | 47 | gitLessonAdapter = 48 | GitLessonAdapter( 49 | requireContext(), 50 | gitLessonList.gitLessons, 51 | ::onLessonItemClicked 52 | ) 53 | 54 | //set recycler view 55 | binding.rvGitInfo.apply { 56 | setHasFixedSize(true) 57 | layoutManager = GridLayoutManager(requireContext(), 2) 58 | adapter = gitLessonAdapter 59 | } 60 | 61 | } 62 | 63 | private fun onLessonItemClicked(currentLesson: Int) { 64 | val action = MainFragmentDirections.actionMainFragmentToLessonFragment(currentLesson) 65 | findNavController().navigate(action) 66 | } 67 | 68 | override fun onDestroyView() { 69 | super.onDestroyView() 70 | _binding = null 71 | } 72 | 73 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/fragments/LessonFragment.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.fragments 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import android.view.animation.AnimationUtils 8 | import androidx.fragment.app.Fragment 9 | import androidx.navigation.fragment.findNavController 10 | import androidx.navigation.fragment.navArgs 11 | import androidx.recyclerview.widget.LinearLayoutManager 12 | import com.vishal2376.gitcoach.MainActivity 13 | import com.vishal2376.gitcoach.R 14 | import com.vishal2376.gitcoach.adapters.GitLessonStepAdapter 15 | import com.vishal2376.gitcoach.databinding.FragmentLessonBinding 16 | import com.vishal2376.gitcoach.models.lesson.GitLesson 17 | import com.vishal2376.gitcoach.utils.LoadData 18 | import com.vishal2376.gitcoach.utils.LoadSettings 19 | 20 | class LessonFragment : Fragment() { 21 | 22 | private var _binding: FragmentLessonBinding? = null 23 | private val binding get() = _binding!! 24 | 25 | private val args: LessonFragmentArgs by navArgs() 26 | 27 | private lateinit var gitLessonStepAdapter: GitLessonStepAdapter 28 | private lateinit var gitLessonList: GitLesson 29 | 30 | override fun onCreateView( 31 | inflater: LayoutInflater, container: ViewGroup?, 32 | savedInstanceState: Bundle? 33 | ): View { 34 | //load settings 35 | LoadSettings.loadTheme(requireContext()) 36 | 37 | // Inflate the layout for this fragment 38 | _binding = FragmentLessonBinding.inflate(inflater, container, false) 39 | 40 | return binding.root 41 | } 42 | 43 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 44 | super.onViewCreated(view, savedInstanceState) 45 | 46 | initUI() 47 | handleButtons() 48 | 49 | //get json data 50 | gitLessonList = LoadData.getGitLessonData(requireContext())!! 51 | 52 | gitLessonStepAdapter = 53 | GitLessonStepAdapter(requireContext(), gitLessonList.gitLessons[args.position]) 54 | 55 | //set recycler view 56 | binding.rvLessonStep.apply { 57 | setHasFixedSize(true) 58 | layoutManager = LinearLayoutManager(requireContext()) 59 | adapter = gitLessonStepAdapter 60 | } 61 | 62 | 63 | //update title 64 | binding.tvLessonTitle.text = gitLessonList.gitLessons[args.position].LessonTitle 65 | } 66 | 67 | private fun handleButtons() { 68 | binding.tvLessonTitle.setOnClickListener { 69 | findNavController().popBackStack() 70 | } 71 | } 72 | 73 | private fun initUI() { 74 | binding.tvLessonTitle.animation = 75 | AnimationUtils.loadAnimation(requireContext(), R.anim.slide_down_anim) 76 | } 77 | 78 | override fun onResume() { 79 | super.onResume() 80 | MainActivity.appBarLayout.visibility = View.GONE 81 | } 82 | 83 | override fun onDestroy() { 84 | super.onDestroy() 85 | MainActivity.appBarLayout.visibility = View.VISIBLE 86 | _binding = null 87 | } 88 | 89 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/fragments/MainFragment.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.fragments 2 | 3 | import android.content.Context.MODE_PRIVATE 4 | import android.os.Bundle 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import androidx.fragment.app.Fragment 9 | import com.google.android.material.tabs.TabLayoutMediator 10 | import com.vishal2376.gitcoach.adapters.ViewPagerAdapter 11 | import com.vishal2376.gitcoach.databinding.FragmentMainBinding 12 | import com.vishal2376.gitcoach.utils.LoadSettings 13 | 14 | class MainFragment : Fragment() { 15 | 16 | private var _binding: FragmentMainBinding? = null 17 | private val binding get() = _binding!! 18 | 19 | override fun onCreateView( 20 | inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? 21 | ): View { 22 | //load settings 23 | LoadSettings.loadTheme(requireContext()) 24 | 25 | // Inflate the layout for this fragment 26 | _binding = FragmentMainBinding.inflate(inflater, container, false) 27 | 28 | return binding.root 29 | } 30 | 31 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 32 | super.onViewCreated(view, savedInstanceState) 33 | 34 | 35 | val viewPagerAdapter = ViewPagerAdapter(childFragmentManager, lifecycle) 36 | binding.viewPager.adapter = viewPagerAdapter 37 | 38 | TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position -> 39 | when (position) { 40 | 0 -> { 41 | tab.text = "Learn" 42 | } 43 | 44 | 1 -> { 45 | tab.text = "Reference" 46 | } 47 | 48 | 2 -> { 49 | tab.text = "Quiz" 50 | } 51 | } 52 | }.attach() 53 | 54 | binding.btnChangeTheme.setOnClickListener { 55 | changeUserTheme() 56 | restartApp() 57 | } 58 | 59 | } 60 | 61 | private fun restartApp() { 62 | val intent = requireActivity().intent 63 | requireActivity().let { 64 | it.finish() 65 | it.startActivity(intent) 66 | } 67 | 68 | } 69 | 70 | private fun changeUserTheme() { 71 | val themes = listOf("yellow", "red", "green", "blue") 72 | var newThemeIndex = 0 73 | 74 | //get current theme 75 | val sp = requireContext().getSharedPreferences("SETTINGS", MODE_PRIVATE) 76 | .getString("user_theme", "yellow") 77 | 78 | newThemeIndex = when (sp.toString()) { 79 | "red" -> { 80 | 1 81 | } 82 | 83 | "green" -> { 84 | 2 85 | } 86 | 87 | "blue" -> { 88 | 3 89 | } 90 | 91 | else -> { 92 | 0 93 | } 94 | } 95 | 96 | requireContext().getSharedPreferences("SETTINGS", MODE_PRIVATE).edit() 97 | .putString("user_theme", themes[++newThemeIndex % themes.size]).apply() 98 | } 99 | 100 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/fragments/SettingsFragment.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.fragments 2 | 3 | import android.content.Context.MODE_PRIVATE 4 | import android.content.Intent 5 | import android.os.Bundle 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import android.view.animation.AnimationUtils 10 | import android.widget.Toast 11 | import androidx.fragment.app.Fragment 12 | import androidx.navigation.fragment.findNavController 13 | import com.vishal2376.gitcoach.MainActivity 14 | import com.vishal2376.gitcoach.R 15 | import com.vishal2376.gitcoach.databinding.FragmentSettingsBinding 16 | import com.vishal2376.gitcoach.utils.Constants 17 | import com.vishal2376.gitcoach.utils.LoadSettings 18 | import com.vishal2376.gitcoach.utils.LocaleHelper 19 | 20 | class SettingsFragment : Fragment() { 21 | 22 | private var _binding: FragmentSettingsBinding? = null 23 | private val binding get() = _binding!! 24 | 25 | override fun onCreateView( 26 | inflater: LayoutInflater, container: ViewGroup?, 27 | savedInstanceState: Bundle? 28 | ): View { 29 | // Inflate the layout for this fragment 30 | _binding = FragmentSettingsBinding.inflate(inflater, container, false) 31 | return binding.root 32 | } 33 | 34 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 35 | super.onViewCreated(view, savedInstanceState) 36 | 37 | initUI() 38 | handleButtons() 39 | 40 | } 41 | 42 | private fun initUI() { 43 | loadDefaultValue() 44 | initAnimation() 45 | } 46 | 47 | private fun loadDefaultValue() { 48 | val locale = LoadSettings.getLocale(requireContext()) 49 | val currentLanguage = when (locale) { 50 | "en" -> binding.rgEnglish 51 | "zh" -> binding.rbChinese 52 | "de" -> binding.rgGerman 53 | "it" -> binding.rgItalian 54 | "pt" -> binding.rgPortuguese 55 | "ru" -> binding.rgRussian 56 | "es" -> binding.rgSpanish 57 | "tr" -> binding.rbTurkish 58 | else -> binding.rgEnglish 59 | } 60 | currentLanguage.isChecked = true 61 | } 62 | 63 | private fun initAnimation() { 64 | binding.tvSettingsTitle.animation = 65 | AnimationUtils.loadAnimation(requireContext(), R.anim.slide_down_anim) 66 | 67 | } 68 | 69 | private fun handleButtons() { 70 | 71 | binding.tvSettingsTitle.setOnClickListener { 72 | findNavController().popBackStack() 73 | } 74 | 75 | binding.btnSave.setOnClickListener { 76 | 77 | 78 | val selectedLanguageLocale = when (binding.rgLanguage.checkedRadioButtonId) { 79 | R.id.rgEnglish -> "en" 80 | R.id.rbChinese -> "zh" 81 | R.id.rgGerman -> "de" 82 | R.id.rgItalian -> "it" 83 | R.id.rgPortuguese -> "pt" 84 | R.id.rgRussian -> "ru" 85 | R.id.rgSpanish -> "es" 86 | R.id.rbTurkish -> "tr" 87 | else -> "en" 88 | } 89 | 90 | //save language locale 91 | saveLocaleCode(selectedLanguageLocale) 92 | 93 | //update language in app 94 | updateLocale(selectedLanguageLocale) 95 | 96 | Toast.makeText(requireContext(), "Language Changed", Toast.LENGTH_SHORT).show() 97 | 98 | restartApp() 99 | } 100 | } 101 | 102 | private fun restartApp() { 103 | val intent = Intent(requireContext(), MainActivity::class.java) 104 | intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) 105 | startActivity(intent) 106 | requireActivity().finish() 107 | } 108 | 109 | private fun updateLocale(selectedLocale: String) { 110 | val updatedContext = LocaleHelper.setLocale(requireContext(), selectedLocale) 111 | resources.updateConfiguration( 112 | updatedContext.resources.configuration, 113 | updatedContext.resources.displayMetrics 114 | ) 115 | } 116 | 117 | 118 | private fun saveLocaleCode(selectedLanguageLocale: String) { 119 | val sharedPreferences = 120 | requireContext().getSharedPreferences("SETTINGS", MODE_PRIVATE) 121 | val editor = sharedPreferences.edit() 122 | editor.putString(Constants.LOCALE, selectedLanguageLocale).apply() 123 | } 124 | 125 | override fun onResume() { 126 | super.onResume() 127 | MainActivity.appBarLayout.visibility = View.GONE 128 | } 129 | 130 | override fun onDestroy() { 131 | super.onDestroy() 132 | MainActivity.appBarLayout.visibility = View.VISIBLE 133 | _binding = null 134 | } 135 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/models/GitCommand.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.models 2 | 3 | data class GitCommand( 4 | val gitCommands: List 5 | ) 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/models/GitCommandItem.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.models 2 | 3 | data class GitCommandItem( 4 | val name: String, val command: String, val description: String, val example: String 5 | ) 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/models/lesson/GitLesson.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.models.lesson 2 | 3 | data class GitLesson( 4 | val gitLessons: List 5 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/models/lesson/GitLessonItem.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.models.lesson 2 | 3 | data class GitLessonItem( 4 | val LessonTitle: String, 5 | val Steps: List 6 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/models/lesson/Step.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.models.lesson 2 | 3 | data class Step( 4 | val Description: String, 5 | val Example: String, 6 | val Explanation: String, 7 | val StepNumber: Int 8 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/models/quiz/GitQuiz.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.models.quiz 2 | 3 | data class GitQuiz( 4 | val quiz: List 5 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/models/quiz/Quiz.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.models.quiz 2 | 3 | data class Quiz( 4 | val choices: List, 5 | val correctAnswer: String, 6 | val id: Int, 7 | val question: String 8 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/utils/Category.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.utils 2 | 3 | object Category { 4 | const val FS_TITLE = "fs-title" 5 | const val FS_SUB_TITLE = "fs-sub-title" 6 | const val FS_DESCRIPTION = "fs-description" 7 | const val FS_COMMAND = "fs-command" 8 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/utils/Constants.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.utils 2 | 3 | object Constants { 4 | const val email = "vishalsingh2376@gmail.com" 5 | var shareMessage = 6 | "Become a Git expert with Git Coach! Learn Git and GitHub commands with ease. Download now\n" 7 | 8 | const val GOOGLE_PLAY_DEV_LINK = "https://play.google.com/store/apps/dev?id=8204011415367950940" 9 | const val SOURCE_CODE_LINK = "https://github.com/vishal2376/git-coach" 10 | const val GITHUB_LINK = "https://github.com/vishal2376/" 11 | const val LINKEDIN_LINK = "https://www.linkedin.com/in/vishal2376/" 12 | const val INSTAGRAM_LINK = "https://www.instagram.com/vishal_2376/" 13 | const val TWITTER_LINK = "https://twitter.com/vishal2376" 14 | 15 | // Settings 16 | const val LOCALE = "locale" 17 | const val FONT_SIZE_TITLE = 18f 18 | const val FONT_SIZE_SUB_TITLE = 14f 19 | const val FONT_SIZE_DESCRIPTION = 13f 20 | const val FONT_SIZE_COMMAND = 16f 21 | 22 | const val CORRECT_ANSWERS = "correct" 23 | const val INCORRECT_ANSWERS = "incorrect" 24 | const val DEFAULT_QUIZ_TOTAL_QUESTIONS = 10 25 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/utils/LoadData.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.utils 2 | 3 | import android.content.Context 4 | import android.content.res.AssetManager 5 | import com.google.gson.Gson 6 | import com.vishal2376.gitcoach.models.GitCommand 7 | import com.vishal2376.gitcoach.models.lesson.GitLesson 8 | import com.vishal2376.gitcoach.models.quiz.GitQuiz 9 | 10 | object LoadData { 11 | 12 | fun getGitCommandData(context: Context): GitCommand? { 13 | val locale = LoadSettings.getLocale(context) 14 | val fileName = "$locale/git_commands.json" 15 | val jsonString = if (isAssetAvailable(context, fileName)) { 16 | context.assets.readFile(fileName) 17 | } else { 18 | context.assets.readFile("en/git_commands.json") 19 | } 20 | return Gson().fromJson(jsonString, GitCommand::class.java) 21 | } 22 | 23 | fun getGitLessonData(context: Context): GitLesson? { 24 | val locale = LoadSettings.getLocale(context) 25 | val fileName = "$locale/git_lessons.json" 26 | val jsonString = if (isAssetAvailable(context, fileName)) { 27 | context.assets.readFile(fileName) 28 | } else { 29 | context.assets.readFile("en/git_lessons.json") 30 | } 31 | return Gson().fromJson(jsonString, GitLesson::class.java) 32 | } 33 | 34 | fun getGitQuizData(context: Context): GitQuiz? { 35 | val locale = LoadSettings.getLocale(context) 36 | val fileName = "$locale/git_quiz.json" 37 | val jsonString = if (isAssetAvailable(context, fileName)) { 38 | context.assets.readFile(fileName) 39 | } else { 40 | context.assets.readFile("en/git_quiz.json") 41 | } 42 | return Gson().fromJson(jsonString, GitQuiz::class.java) 43 | } 44 | 45 | private fun isAssetAvailable(context: Context, fileName: String): Boolean { 46 | return try { 47 | context.assets.open(fileName).close() 48 | true 49 | } catch (e: Exception) { 50 | false 51 | } 52 | } 53 | 54 | private fun AssetManager.readFile(fileName: String) = open(fileName) 55 | .bufferedReader() 56 | .use { it.readText() } 57 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/utils/LoadSettings.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.utils 2 | 3 | import android.content.Context 4 | import android.content.Context.MODE_PRIVATE 5 | import com.vishal2376.gitcoach.R 6 | 7 | object LoadSettings { 8 | 9 | fun loadTheme(context: Context) { 10 | //load saved values 11 | val sp = 12 | context.getSharedPreferences("SETTINGS", MODE_PRIVATE).getString("user_theme", "blue") 13 | 14 | when (sp.toString()) { 15 | "red" -> { 16 | context.setTheme(R.style.Theme_RED) 17 | } 18 | 19 | "yellow" -> { 20 | context.setTheme(R.style.Theme_YELLOW) 21 | } 22 | 23 | "green" -> { 24 | context.setTheme(R.style.Theme_GREEN) 25 | } 26 | 27 | else -> { 28 | context.setTheme(R.style.Theme_GitCoach) 29 | } 30 | } 31 | } 32 | 33 | fun getFontSize(context: Context, category: String): Float { 34 | return context.getSharedPreferences("SETTINGS", MODE_PRIVATE) 35 | .getFloat(category, 0f) 36 | } 37 | 38 | fun getLocale(context: Context): String { 39 | return context.getSharedPreferences("SETTINGS", MODE_PRIVATE) 40 | .getString(Constants.LOCALE, "en").toString() 41 | } 42 | } -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/utils/LocaleHelper.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.utils 2 | 3 | import android.content.Context 4 | import android.content.res.Configuration 5 | import java.util.Locale 6 | 7 | object LocaleHelper { 8 | 9 | fun setLocale(context: Context, language: String): Context { 10 | return updateResources(context, language) 11 | } 12 | 13 | private fun updateResources(context: Context, language: String): Context { 14 | val locale = Locale(language) 15 | Locale.setDefault(locale) 16 | 17 | val resources = context.resources 18 | val configuration = Configuration(resources.configuration) 19 | 20 | configuration.setLocale(locale) 21 | 22 | return context.createConfigurationContext(configuration) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/vishal2376/gitcoach/utils/Util.kt: -------------------------------------------------------------------------------- 1 | package com.vishal2376.gitcoach.utils 2 | 3 | import android.content.ClipData 4 | import android.content.ClipboardManager 5 | import android.content.Context 6 | import android.content.Intent 7 | 8 | fun shareCommand(context: Context, command: String) { 9 | val shareIntent = Intent() 10 | shareIntent.action = Intent.ACTION_SEND 11 | shareIntent.type = "text/plain" 12 | shareIntent.putExtra(Intent.EXTRA_TEXT, command) 13 | context.startActivity(Intent.createChooser(shareIntent, "Share Command")) 14 | } 15 | 16 | fun copyToClipboard(context: Context, text: String) { 17 | val clipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager 18 | val clipData = ClipData.newPlainText("Git Command", text) 19 | clipboardManager.setPrimaryClip(clipData) 20 | } -------------------------------------------------------------------------------- /app/src/main/res/anim/alpha_anim.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/anim/bounce_anim.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 | 19 | 20 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/anim/popup_anim.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_down_anim.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_up_anim.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/app_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishal2376/git-coach/4d0411571b0b514136fb3714caa9ef808a9b4b54/app/src/main/res/drawable/app_logo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/app_logo_svg.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 13 | 16 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/box_round_border.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/box_stroke_round_blue.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/box_stroke_round_gray.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/box_stroke_round_red.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bug_report.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/circle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/developer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishal2376/git-coach/4d0411571b0b514136fb3714caa9ef808a9b4b54/app/src/main/res/drawable/developer.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishal2376/git-coach/4d0411571b0b514136fb3714caa9ef808a9b4b54/app/src/main/res/drawable/github.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_check.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_code.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_developer.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_font_size.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_left_arrow.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_more_apps.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_notification.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_palette.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_rate_start.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_search.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_share.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_suggestions.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_translate.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/instagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishal2376/git-coach/4d0411571b0b514136fb3714caa9ef808a9b4b54/app/src/main/res/drawable/instagram.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/item_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/item_bg_green.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/item_bg_red.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/item_lesson_bg_unlocked.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/line_circle.xml: -------------------------------------------------------------------------------- 1 | 6 | 11 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/linkedin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishal2376/git-coach/4d0411571b0b514136fb3714caa9ef808a9b4b54/app/src/main/res/drawable/linkedin.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/radio_bg_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/radio_correct_choice_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/round_bg_dark.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishal2376/git-coach/4d0411571b0b514136fb3714caa9ef808a9b4b54/app/src/main/res/drawable/twitter.png -------------------------------------------------------------------------------- /app/src/main/res/font/roboto_medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishal2376/git-coach/4d0411571b0b514136fb3714caa9ef808a9b4b54/app/src/main/res/font/roboto_medium.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/rubik_medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishal2376/git-coach/4d0411571b0b514136fb3714caa9ef808a9b4b54/app/src/main/res/font/rubik_medium.ttf -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 15 | 16 | 27 | 28 | 40 | 41 | 47 | 48 | 57 | 58 | 66 | 67 | 68 | 69 | 80 | 81 | 82 | 83 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_splash_screen.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 21 | 22 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_community.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 22 | 23 | 27 | 28 | 36 | 37 | 44 | 45 | 53 | 54 | 61 | 62 | 63 | 68 | 69 | 80 | 81 | 93 | 94 | 95 | 96 | 97 | 98 | 99 |