Merge branch 'master' into crash_screen

This commit is contained in:
Yogesh Choudhary Paliyal
2021-12-12 11:44:05 +05:30
committed by GitHub
130 changed files with 1790 additions and 483 deletions

14
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,14 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "gradle"
directory: "/"
schedule:
interval: "daily"
commit-message:
prefix: "[Android]"

43
.github/workflows/android.yaml vendored Normal file
View File

@@ -0,0 +1,43 @@
name: Android CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: 🧱 Set Up JDK
uses: actions/setup-java@v1
with:
java-version: 11
- name: Grant Gradlew rights
run: chmod +x gradlew
- name: 🧪 Run Tests
run: ./gradlew test
- name: 🛠 Build Project with Spotless Check
run: ./gradlew spotlessCheck
- name: ⏳ Build with Gradle
run: ./gradlew build
- name: 🏗 Build APK
run: bash ./gradlew assembleProductionDebug --stacktrace
- name: 🚀 Upload APK 📱
uses: actions/upload-artifact@v2
with:
name: app
path: app/build/outputs/apk/production/debug/*.apk
retention-days: 3

103
.github/workflows/detekt-analysis.yml vendored Normal file
View File

@@ -0,0 +1,103 @@
# This workflow performs a static analysis of your Kotlin source code using
# Detekt.
#
# Scans are triggered:
# 1. On every push to default and protected branches
# 2. On every Pull Request targeting the default branch
# 3. On a weekly schedule
# 4. Manually, on demand, via the "workflow_dispatch" event
#
# The workflow should work with no modifications, but you might like to use a
# later version of the Detekt CLI by modifing the $DETEKT_RELEASE_TAG
# environment variable.
name: Scan with Detekt
on:
# Triggers the workflow on push or pull request events but only for default and protected branches
push:
branches: [ master ]
pull_request:
branches: [ master ]
schedule:
- cron: '19 0 * * 2'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
env:
# Release tag associated with version of Detekt to be installed
# SARIF support (required for this workflow) was introduced in Detekt v1.15.0
DETEKT_RELEASE_TAG: v1.15.0
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "scan"
scan:
name: Scan
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
# Gets the download URL associated with the $DETEKT_RELEASE_TAG
- name: Get Detekt download URL
id: detekt_info
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
DETEKT_DOWNLOAD_URL=$( gh api graphql --field tagName=$DETEKT_RELEASE_TAG --raw-field query='
query getReleaseAssetDownloadUrl($tagName: String!) {
repository(name: "detekt", owner: "detekt") {
release(tagName: $tagName) {
releaseAssets(name: "detekt", first: 1) {
nodes {
downloadUrl
}
}
}
}
}
' | \
jq --raw-output '.data.repository.release.releaseAssets.nodes[0].downloadUrl' )
echo "::set-output name=download_url::$DETEKT_DOWNLOAD_URL"
# Sets up the detekt cli
- name: Setup Detekt
run: |
dest=$( mktemp -d )
curl --request GET \
--url ${{ steps.detekt_info.outputs.download_url }} \
--silent \
--location \
--output $dest/detekt
chmod a+x $dest/detekt
echo $dest >> $GITHUB_PATH
# Performs static analysis using Detekt
- name: Run Detekt
continue-on-error: true
run: |
detekt --input ${{ github.workspace }} --report sarif:${{ github.workspace }}/detekt.sarif.json
# Modifies the SARIF output produced by Detekt so that absolute URIs are relative
# This is so we can easily map results onto their source files
# This can be removed once relative URI support lands in Detekt: https://git.io/JLBbA
- name: Make artifact location URIs relative
continue-on-error: true
run: |
echo "$(
jq \
--arg github_workspace ${{ github.workspace }} \
'. | ( .runs[].results[].locations[].physicalLocation.artifactLocation.uri |= if test($github_workspace) then .[($github_workspace | length | . + 1):] else . end )' \
${{ github.workspace }}/detekt.sarif.json
)" > ${{ github.workspace }}/detekt.sarif.json
# Uploads results to GitHub repository using the upload-sarif action
- uses: github/codeql-action/upload-sarif@v1
with:
# Path to SARIF file relative to the root of the repository
sarif_file: ${{ github.workspace }}/detekt.sarif.json
checkout_path: ${{ github.workspace }}

2
.idea/gradle.xml generated
View File

@@ -12,6 +12,8 @@
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/common" />
<option value="$PROJECT_DIR$/keypasscompose" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />

View File

@@ -31,5 +31,10 @@
<option name="name" value="maven2" />
<option name="url" value="https://maven.localazy.com/repository/release/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
</component>
</project>

15
.idea/misc.xml generated
View File

@@ -5,14 +5,23 @@
<map>
<entry key="../../../../layout/custom_preview.xml" value="0.20833333333333334" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/drawable/ic_twotone_content_copy_24.xml" value="0.10989583333333333" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/drawable/ic_undraw_empty_street_sfxm.xml" value="0.21614583333333334" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/drawable/nav_divider_top.xml" value="0.21614583333333334" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/layout/activity_add_totpactivity.xml" value="0.16485507246376813" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/layout/activity_crash.xml" value="0.14" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/layout/activity_dashboard.xml" value="0.2" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/layout/activity_scanner.xml" value="0.10416666666666667" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/layout/fragment_bottom_nav_drawer.xml" value="0.2" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/layout/fragment_detail.xml" value="0.1403985507246377" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/layout/fragment_home.xml" value="0.16304347826086957" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/layout/item_accounts.xml" value="0.1" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/layout/item_totp.xml" value="0.5585331452750353" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/layout/item_accounts.xml" value="0.388259526261586" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/layout/item_totp.xml" value="0.2" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/layout/layout_backup_keypharse.xml" value="0.15353260869565216" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/layout/layout_no_accounts.xml" value="0.17074275362318841" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/layout/nav_divider_item_layout.xml" value="0.2" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/layout/nav_email_folder_item_layout.xml" value="0.2" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/layout/nav_menu_item_layout.xml" value="0.2" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/menu/bottom_app_bar_detail.xml" value="0.2" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/menu/menu_delete.xml" value="0.2" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/main/res/xml/backup_preferences.xml" value="0.4287690179806362" />
<entry key="..\:/Users/paliy/StudioProjects/KeyPass/app/src/production/res/mipmap-anydpi-v26/ic_launcher.xml" value="0.21614583333333334" />

View File

@@ -1,14 +1,16 @@
# KeyPass : Offline Password Manager
<h1 align="center"> KeyPass : Offline Password Manager</h1>
<p align="center"></p>
![GitHub release (latest by date)](https://img.shields.io/github/v/release/yogeshpaliyal/KeyPass?style=for-the-badge)
<div align="center">
<img src="https://img.shields.io/github/v/release/yogeshpaliyal/KeyPass?style=for-the-badge" />
<img src="https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Fyogeshpaliyal%2FKeyPass&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=true&style=for-the-badge" />
</div>
![Cover Image](https://github.com/yogeshpaliyal/KeyPass/raw/master/images/KeyPass%20Cover.jpg)
| | | | | |
|--|--|--|--|--|
|<img src ="https://github.com/yogeshpaliyal/KeyPass/blob/master/images/image1.png?raw=true" width="100%"/>|<img src ="https://github.com/yogeshpaliyal/KeyPass/blob/master/images/image2.png?raw=true" width="100%"/>|<img src ="https://github.com/yogeshpaliyal/KeyPass/blob/master/images/image3.png?raw=true" width="100%"/>|<img src ="https://github.com/yogeshpaliyal/KeyPass/blob/master/images/image4.png?raw=true" width="100%"/> |<img src ="https://github.com/yogeshpaliyal/KeyPass/blob/master/images/image5.png?raw=true" width="100%"/>
<div style="display: inline-block" align="center">
<img src ="https://github.com/yogeshpaliyal/KeyPass/blob/master/images/image1.png?raw=true" width="19%"/><img src ="https://github.com/yogeshpaliyal/KeyPass/blob/master/images/image2.png?raw=true" width="19%"/><img src ="https://github.com/yogeshpaliyal/KeyPass/blob/master/images/image3.png?raw=true" width="19%"/><img src ="https://github.com/yogeshpaliyal/KeyPass/blob/master/images/image4.png?raw=true" width="19%"/><img src ="https://github.com/yogeshpaliyal/KeyPass/blob/master/images/image5.png?raw=true" width="19%"/>
</div>
@@ -18,11 +20,12 @@
- [x] Open Source : Code is accessible to every one
- [x] Encrypted Backup and Restore
- [x] Dark Mode Support
- [x] Material Design
- [x] Material Design 3
- [x] Screenshot Blocked
- [x] Authenticate with device credentials (pin, pattern, biometrics)
- [x] Auto Backup
- [x] TOTP
- [ ] Jetpack Compose
## 🛠️ Language, Tools & Frameworks Used
@@ -37,4 +40,29 @@
## Download Links
<a href='https://play.google.com/store/apps/details?id=com.yogeshpaliyal.keypass'><img align='center' height='55' src='./icons/google_play_badge.png'></a>
<a href='https://f-droid.org/en/packages/com.yogeshpaliyal.keypass/'><img align='center' alt='Get it on F-Droid' src='./icons/fdroid_badge.png' height="55"/></a>
<a href='https://f-droid.org/en/packages/com.yogeshpaliyal.keypass/'><img align='center' alt='Get it on F-Droid' src='./icons/fdroid_badge.png' height="55"/></a>
```
MIT License
Copyright (c) 2021 Yogesh Choudhary Paliyal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```

View File

@@ -20,8 +20,8 @@ android {
applicationId appPackageId
minSdkVersion 22
targetSdkVersion 31
versionCode 1400
versionName "1.4.0"
versionCode 1401
versionName "1.4.1"
testInstrumentationRunner "com.yogeshpaliyal.keypass.CustomTestRunner"
}
@@ -73,11 +73,13 @@ android {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.5.31"
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
implementation project(":common")
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.6.0"
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.0'
implementation 'com.google.android.material:material:1.6.0-alpha01'
implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
implementation 'androidx.preference:preference-ktx:1.1.1'
testImplementation 'junit:junit:4.13.2'
@@ -106,26 +108,11 @@ dependencies {
implementation "androidx.room:room-ktx:$room_version"
implementation 'com.github.yogeshpaliyal:Android-Universal-Recycler-View-Adapter:2.2.0'
implementation 'com.yogeshpaliyal:universal-adapter:3.0.0'
implementation "androidx.biometric:biometric:1.1.0"
implementation "androidx.preference:preference-ktx:1.1.1"
implementation "androidx.work:work-runtime-ktx:2.6.0"
//Androidx Security
implementation "androidx.security:security-crypto:1.1.0-alpha03"
implementation 'com.google.code.gson:gson:2.8.8'
// dependency injection
implementation("com.google.dagger:hilt-android:$hilt_version")
kapt("com.google.dagger:hilt-android-compiler:$hilt_version")
@@ -136,24 +123,39 @@ dependencies {
// zxing library
// implementation "com.googl.ezxing:android-core:3.4.1"
implementation 'com.journeyapps:zxing-android-embedded:4.2.0'
// apache common codec
implementation "commons-codec:commons-codec:1.15"
implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
// For instrumented tests.
androidTestImplementation("com.google.dagger:hilt-android-testing:2.38.1")
androidTestImplementation("com.google.dagger:hilt-android-testing:2.40.5")
// ...with Kotlin.
kaptAndroidTest("com.google.dagger:hilt-android-compiler:2.38.1")
kaptAndroidTest("com.google.dagger:hilt-android-compiler:2.40")
// For Robolectric tests.
testImplementation("com.google.dagger:hilt-android-testing:2.38.1")
testImplementation("com.google.dagger:hilt-android-testing:2.40.5")
// ...with Kotlin.
kaptTest("com.google.dagger:hilt-android-compiler:2.38.1")
kaptTest("com.google.dagger:hilt-android-compiler:2.40")
// jetpack compose
implementation 'androidx.compose.ui:ui:1.0.5'
implementation 'com.google.code.gson:gson:2.8.9'
implementation 'androidx.compose.ui:ui-tooling:1.0.5'
// Foundation (Border, Background, Box, Image, Scroll, shapes, animations, etc.)
implementation 'androidx.compose.foundation:foundation:1.0.5'
// Material Design
implementation 'androidx.compose.material:material:1.0.5'
// Material design icons
implementation 'androidx.compose.material:material-icons-core:1.0.5'
implementation 'androidx.compose.material:material-icons-extended:1.0.5'
// Integration with activities
implementation 'androidx.activity:activity-compose:1.4.0'
// Integration with ViewModels
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.4.0'
// Integration with observables
implementation 'androidx.compose.runtime:runtime-livedata:1.0.5'
}

View File

@@ -11,4 +11,4 @@ class CustomTestRunner : AndroidJUnitRunner() {
override fun newApplication(cl: ClassLoader?, name: String?, context: Context?): Application {
return super.newApplication(cl, HiltTestApplication::class.java.name, context)
}
}
}

View File

@@ -1,6 +1,5 @@
package com.yogeshpaliyal.keypass.ui.nav
import androidx.test.espresso.Espresso.onData
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.action.ViewActions.replaceText
@@ -8,24 +7,15 @@ import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.*
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.rules.activityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import com.yogeshpaliyal.keypass.AppDatabase
import com.yogeshpaliyal.common.AppDatabase
import com.yogeshpaliyal.common.data.AccountModel
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.data.AccountModel
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.HiltTestApplication
import org.hamcrest.CoreMatchers.not
import org.junit.Assert.*
import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Rule
import org.junit.Test
import org.junit.runner.OrderWith
import org.junit.runner.RunWith
import javax.inject.Inject
@HiltAndroidTest
@@ -35,10 +25,9 @@ class DashboardActivityTest {
@get:Rule(order = 1)
var activityScenarioRule = ActivityScenarioRule(DashboardActivity::class.java)
@Inject
lateinit var appDatabase: AppDatabase
lateinit var appDatabase: com.yogeshpaliyal.common.AppDatabase
@Before
fun setUp() {
@@ -46,8 +35,7 @@ class DashboardActivityTest {
appDatabase.clearAllTables()
}
private fun getDummyAccount() : AccountModel{
private fun getDummyAccount(): AccountModel {
val accountModel = AccountModel()
accountModel.title = "Github ${System.currentTimeMillis()}"
accountModel.username = "yogeshpaliyal"
@@ -59,14 +47,14 @@ class DashboardActivityTest {
}
@Test
fun addAccountAndDetailAndDeleteTest(){
fun addAccountAndDetailAndDeleteTest() {
val accountModel = getDummyAccount()
addAccount(accountModel)
checkAccountDetail(accountModel)
deleteAccount(accountModel)
}
private fun addAccount(accountModel: AccountModel){
private fun addAccount(accountModel: AccountModel) {
// Navigate to add screen
onView(withId(R.id.btnAdd)).perform(click())
@@ -90,9 +78,7 @@ class DashboardActivityTest {
onView(withText(accountModel.username)).check(matches(isDisplayed()))
}
private fun checkAccountDetail(accountModel: AccountModel){
private fun checkAccountDetail(accountModel: AccountModel) {
// Navigate to account detail
onView(withText(accountModel.username)).perform(click())
@@ -109,10 +95,9 @@ class DashboardActivityTest {
onView(withId(R.id.etWebsite)).check(matches(withText(accountModel.password)))
onView(withId(R.id.etNotes)).check(matches(withText(accountModel.notes)))
}
private fun deleteAccount(accountModel: AccountModel){
private fun deleteAccount(accountModel: AccountModel) {
// delete account
onView(withId(R.id.action_delete)).perform(click())
@@ -121,8 +106,4 @@ class DashboardActivityTest {
// is not showing in listing
onView(withText(accountModel.username)).check(doesNotExist())
}
}
}

View File

@@ -6,6 +6,7 @@ import android.util.Log
import androidx.hilt.work.HiltWorkerFactory
import androidx.work.Configuration
import com.yogeshpaliyal.keypass.ui.CrashActivity
import com.google.android.material.color.DynamicColors
import dagger.hilt.android.HiltAndroidApp
import javax.inject.Inject
import kotlin.system.exitProcess
@@ -31,6 +32,8 @@ class MyApplication : Application(), Configuration.Provider {
startActivity(intent)
exitProcess(1)
}
DynamicColors.applyToActivitiesIfAvailable(this)
}
override fun getWorkManagerConfiguration(): Configuration {

View File

@@ -0,0 +1,36 @@
package com.yogeshpaliyal.keypass.data
import com.google.gson.Gson
import com.yogeshpaliyal.common.data.AccountModel
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.constants.AccountType
import com.yogeshpaliyal.universalAdapter.listener.UniversalViewType
import com.yogeshpaliyal.universalAdapter.model.BaseDiffUtil
class MyAccountModel : AccountModel(), BaseDiffUtil, UniversalViewType {
override fun getDiffId(): Any? {
return id
}
override fun getDiffBody(): Any? {
return if (type == AccountType.TOTP) {
super.getDiffBody()
} else {
Gson().toJson(this)
}
}
override fun getLayoutId(): Int = if (type == AccountType.TOTP) R.layout.item_totp else R.layout.item_accounts
fun map(accountModel: AccountModel) {
this.id = accountModel.id
this.title = accountModel.title
this.uniqueId = accountModel.uniqueId
this.username = accountModel.username
this.password = accountModel.password
this.site = accountModel.site
this.notes = accountModel.notes
this.tags = accountModel.tags
this.type = accountModel.type
}
}

View File

@@ -1,29 +0,0 @@
package com.yogeshpaliyal.keypass.data
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.google.gson.annotations.Expose
import com.google.gson.annotations.SerializedName
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.universal_adapter.listener.UniversalViewType
import com.yogeshpaliyal.universal_adapter.model.BaseDiffUtil
@Entity(tableName = "totps")
data class TOtpModel(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
@SerializedName("id")
var id: Long? = null,
@ColumnInfo(name = "unique_id")
@SerializedName("unique_id")
var uniqueId: String? = null,
@Expose
@SerializedName("account_name")
val accountName: String? = null
) : BaseDiffUtil, UniversalViewType {
override fun getLayoutId() = R.layout.item_totp
}

View File

@@ -12,9 +12,9 @@ import androidx.lifecycle.Observer
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import com.google.zxing.integration.android.IntentIntegrator
import com.yogeshpaliyal.common.utils.TOTPHelper
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.databinding.ActivityAddTotpactivityBinding
import com.yogeshpaliyal.keypass.utils.TOTPHelper
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
@@ -85,7 +85,7 @@ class AddTOTPActivity : AppCompatActivity() {
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
override fun onCreateOptionsMenu(menu: Menu): Boolean {
if (accountId != null)
menuInflater.inflate(R.menu.menu_delete, menu)
return super.onCreateOptionsMenu(menu)

View File

@@ -4,18 +4,17 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.yogeshpaliyal.keypass.AppDatabase
import com.yogeshpaliyal.common.data.AccountModel
import com.yogeshpaliyal.common.utils.Event
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.constants.AccountType
import com.yogeshpaliyal.keypass.data.AccountModel
import com.yogeshpaliyal.keypass.utils.Event
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class AddTOTPViewModel @Inject constructor(private val appDatabase: AppDatabase) : ViewModel() {
class AddTOTPViewModel @Inject constructor(private val appDatabase: com.yogeshpaliyal.common.AppDatabase) : ViewModel() {
private val _goBack = MutableLiveData<Event<Unit>>()
val goBack: LiveData<Event<Unit>> = _goBack

View File

@@ -12,7 +12,8 @@ import androidx.preference.Preference
import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceFragmentCompat
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.yogeshpaliyal.keypass.AppDatabase
import com.yogeshpaliyal.common.AppDatabase
import com.yogeshpaliyal.common.utils.*
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.databinding.BackupActivityBinding
import com.yogeshpaliyal.keypass.databinding.LayoutBackupKeypharseBinding
@@ -60,7 +61,7 @@ class BackupActivity : AppCompatActivity() {
lateinit var sp: SharedPreferences
@Inject
lateinit var appDb: AppDatabase
lateinit var appDb: com.yogeshpaliyal.common.AppDatabase
private val CHOOSE_BACKUPS_LOCATION_REQUEST_CODE = 26212

View File

@@ -8,9 +8,9 @@ import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.yogeshpaliyal.common.utils.PasswordGenerator
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.databinding.FragmentDetailBinding
import com.yogeshpaliyal.keypass.utils.PasswordGenerator
import dagger.hilt.android.AndroidEntryPoint
/*
@@ -107,7 +107,7 @@ class DetailActivity : AppCompatActivity() {
}.show()
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.bottom_app_bar_detail, menu)
return super.onCreateOptionsMenu(menu)
}

View File

@@ -6,9 +6,8 @@ import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.yogeshpaliyal.keypass.AppDatabase
import com.yogeshpaliyal.keypass.data.AccountModel
import com.yogeshpaliyal.keypass.worker.executeAutoBackup
import com.yogeshpaliyal.common.data.AccountModel
import com.yogeshpaliyal.common.worker.executeAutoBackup
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -22,7 +21,7 @@ import javax.inject.Inject
* created on 31-01-2021 11:52
*/
@HiltViewModel
class DetailViewModel @Inject constructor(val app: Application, val appDb: AppDatabase, val sp: SharedPreferences) : AndroidViewModel(app) {
class DetailViewModel @Inject constructor(val app: Application, val appDb: com.yogeshpaliyal.common.AppDatabase, val sp: SharedPreferences) : AndroidViewModel(app) {
private val _accountModel by lazy { MutableLiveData<AccountModel>() }
val accountModel: LiveData<AccountModel> = _accountModel

View File

@@ -5,10 +5,9 @@ import android.content.ClipboardManager
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.getSystemService
import com.yogeshpaliyal.common.utils.PasswordGenerator
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.databinding.ActivityGeneratePasswordBinding
import com.yogeshpaliyal.keypass.utils.PasswordGenerator
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
@@ -35,12 +34,14 @@ class GeneratePasswordActivity : AppCompatActivity() {
private fun generatePassword() {
val password = PasswordGenerator(
binding.sliderPasswordLength.value.toInt(), binding.cbCapAlphabets.isChecked,
binding.cbLowerAlphabets.isChecked,
binding.cbSymbols.isChecked,
binding.cbNumbers.isChecked
length = binding.sliderPasswordLength.value.toInt(),
includeUpperCaseLetters = binding.cbCapAlphabets.isChecked,
includeLowerCaseLetters = binding.cbLowerAlphabets.isChecked,
includeSymbols = binding.cbSymbols.isChecked,
includeNumbers = binding.cbNumbers.isChecked
).generatePassword()
binding.etPassword.setText(password)
binding.etPassword.setSelection(password.length)
}
}

View File

@@ -2,8 +2,8 @@ package com.yogeshpaliyal.keypass.ui.home
import android.app.Application
import androidx.lifecycle.*
import com.yogeshpaliyal.keypass.AppDatabase
import com.yogeshpaliyal.keypass.data.AccountModel
import com.yogeshpaliyal.common.AppDatabase
import com.yogeshpaliyal.common.data.AccountModel
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
@@ -17,7 +17,7 @@ import javax.inject.Inject
* created on 30-01-2021 23:02
*/
@HiltViewModel
class DashboardViewModel @Inject constructor(application: Application, val appDb: AppDatabase) :
class DashboardViewModel @Inject constructor(application: Application, val appDb: com.yogeshpaliyal.common.AppDatabase) :
AndroidViewModel(application) {
val keyword by lazy {

View File

@@ -11,16 +11,17 @@ import androidx.activity.viewModels
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import com.yogeshpaliyal.common.data.AccountModel
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.constants.AccountType
import com.yogeshpaliyal.keypass.data.AccountModel
import com.yogeshpaliyal.keypass.data.MyAccountModel
import com.yogeshpaliyal.keypass.databinding.FragmentHomeBinding
import com.yogeshpaliyal.keypass.listener.AccountsClickListener
import com.yogeshpaliyal.keypass.ui.addTOTP.AddTOTPActivity
import com.yogeshpaliyal.keypass.ui.detail.DetailActivity
import com.yogeshpaliyal.universal_adapter.adapter.UniversalAdapterViewType
import com.yogeshpaliyal.universal_adapter.adapter.UniversalRecyclerAdapter
import com.yogeshpaliyal.universal_adapter.utils.Resource
import com.yogeshpaliyal.universalAdapter.adapter.UniversalAdapterViewType
import com.yogeshpaliyal.universalAdapter.adapter.UniversalRecyclerAdapter
import com.yogeshpaliyal.universalAdapter.utils.Resource
import dagger.hilt.android.AndroidEntryPoint
/*
@@ -38,7 +39,7 @@ class HomeFragment : Fragment() {
}
private val mAdapter by lazy {
UniversalRecyclerAdapter.Builder<AccountModel>(
UniversalRecyclerAdapter.Builder<MyAccountModel>(
this,
content = UniversalAdapterViewType.Content(
R.layout.item_accounts,
@@ -65,7 +66,8 @@ class HomeFragment : Fragment() {
)
val clip = ClipData.newPlainText("KeyPass", model.password)
clipboard?.setPrimaryClip(clip)
Toast.makeText(context, getString(R.string.copied_to_clipboard), Toast.LENGTH_SHORT).show()
Toast.makeText(context, getString(R.string.copied_to_clipboard), Toast.LENGTH_SHORT)
.show()
}
}
@@ -79,8 +81,10 @@ class HomeFragment : Fragment() {
}
private val observer = Observer<List<AccountModel>> {
val newList = it.map {
it.copy(id = it.id, title = it.title, uniqueId = it.uniqueId, username = it.username, it.password, it.site, it.notes, it.tags, it.type)
val newList = it.map { accountModel ->
MyAccountModel().also {
it.map(accountModel)
}
}
mAdapter.updateData(Resource.success(ArrayList(newList)))
}

View File

@@ -8,7 +8,6 @@ import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.activity.OnBackPressedCallback
import androidx.activity.viewModels
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.observe
@@ -19,9 +18,9 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HALF_EX
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN
import com.google.android.material.bottomsheet.BottomSheetBehavior.from
import com.google.android.material.shape.MaterialShapeDrawable
import com.yogeshpaliyal.common.utils.themeColor
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.databinding.FragmentBottomNavDrawerBinding
import com.yogeshpaliyal.keypass.utils.themeColor
import dagger.hilt.android.AndroidEntryPoint
import kotlin.LazyThreadSafetyMode.NONE
@@ -55,7 +54,7 @@ class BottomNavDrawerFragment :
0
).apply {
fillColor = ColorStateList.valueOf(
foregroundContext.themeColor(R.attr.colorPrimarySurface)
foregroundContext.themeColor(R.attr.colorSurface)
)
elevation = resources.getDimension(R.dimen.plane_16)
shadowCompatibilityMode = MaterialShapeDrawable.SHADOW_COMPAT_MODE_NEVER

View File

@@ -5,7 +5,7 @@ import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.yogeshpaliyal.keypass.AppDatabase
import com.yogeshpaliyal.common.AppDatabase
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
@@ -18,7 +18,7 @@ import javax.inject.Inject
* created on 31-01-2021 14:11
*/
@HiltViewModel
class BottomNavViewModel @Inject constructor (application: Application, val appDb: AppDatabase) : AndroidViewModel(application) {
class BottomNavViewModel @Inject constructor (application: Application, val appDb: com.yogeshpaliyal.common.AppDatabase) : AndroidViewModel(application) {
private val _navigationList: MutableLiveData<List<NavigationModelItem>> = MutableLiveData()
private val tagsDb = appDb.getDao().getTags()

View File

@@ -5,7 +5,7 @@ import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout
import com.google.android.material.R
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.yogeshpaliyal.keypass.utils.normalize
import com.yogeshpaliyal.common.utils.normalize
import kotlin.math.max
/**

View File

@@ -3,7 +3,7 @@ package com.yogeshpaliyal.keypass.ui.nav
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.recyclerview.widget.DiffUtil
import com.yogeshpaliyal.keypass.data.StringDiffUtil
import com.yogeshpaliyal.common.data.StringDiffUtil
/**
* A sealed class which encapsulates all objects [NavigationAdapter] is able to display.

View File

@@ -7,8 +7,8 @@ import androidx.core.view.marginTop
import androidx.core.view.updatePadding
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.shape.MaterialShapeDrawable
import com.yogeshpaliyal.common.utils.normalize
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.utils.normalize
/**
* An action to be performed when a bottom sheet's slide offset is changed.

View File

@@ -1,7 +1,10 @@
package com.yogeshpaliyal.keypass.ui.settings
import android.app.Activity
import android.content.*
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Intent
import android.content.SharedPreferences
import android.net.Uri
import android.os.Bundle
import android.widget.Toast
@@ -11,15 +14,14 @@ import androidx.lifecycle.lifecycleScope
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.yogeshpaliyal.keypass.AppDatabase
import com.yogeshpaliyal.common.db_helper.createBackup
import com.yogeshpaliyal.common.db_helper.restoreBackup
import com.yogeshpaliyal.common.utils.*
import com.yogeshpaliyal.keypass.BuildConfig
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.databinding.LayoutBackupKeypharseBinding
import com.yogeshpaliyal.keypass.databinding.LayoutRestoreKeypharseBinding
import com.yogeshpaliyal.keypass.db_helper.createBackup
import com.yogeshpaliyal.keypass.db_helper.restoreBackup
import com.yogeshpaliyal.keypass.ui.backup.BackupActivity
import com.yogeshpaliyal.keypass.utils.*
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import javax.inject.Inject
@@ -30,7 +32,7 @@ class MySettingsFragment : PreferenceFragmentCompat() {
private val CHOOSE_RESTORE_FILE_REQUEST_CODE = 26213
@Inject
lateinit var appDb: AppDatabase
lateinit var appDb: com.yogeshpaliyal.common.AppDatabase
@Inject
lateinit var sp: SharedPreferences
@@ -42,7 +44,10 @@ class MySettingsFragment : PreferenceFragmentCompat() {
override fun onPreferenceTreeClick(preference: Preference?): Boolean {
when (preference?.key) {
"feedback" -> {
context?.email(getString(R.string.feedback_to_keypass), "yogeshpaliyal.foss@gmail.com")
context?.email(
getString(R.string.feedback_to_keypass),
"yogeshpaliyal.foss@gmail.com"
)
return true
}
@@ -144,7 +149,11 @@ class MySettingsFragment : PreferenceFragmentCompat() {
"Restore"
) { dialog, which ->
lifecycleScope.launch {
val result = appDb.restoreBackup(binding.etKeyPhrase.text.toString(), contentResolver, selectedFile)
val result = appDb.restoreBackup(
binding.etKeyPhrase.text.toString(),
contentResolver,
selectedFile
)
if (result) {
dialog?.dismiss()
Toast.makeText(
@@ -187,9 +196,16 @@ class MySettingsFragment : PreferenceFragmentCompat() {
binding.txtCode.setOnClickListener {
val clipboard =
getSystemService(requireContext(), ClipboardManager::class.java)
val clip = ClipData.newPlainText(getString(R.string.app_name), binding.txtCode.text)
val clip = ClipData.newPlainText(
getString(R.string.app_name),
binding.txtCode.text
)
clipboard?.setPrimaryClip(clip)
Toast.makeText(context, getString(R.string.copied_to_clipboard), Toast.LENGTH_SHORT).show()
Toast.makeText(
context,
getString(R.string.copied_to_clipboard),
Toast.LENGTH_SHORT
).show()
}
MaterialAlertDialogBuilder(requireContext()).setView(binding.root)
.setPositiveButton(
@@ -198,7 +214,11 @@ class MySettingsFragment : PreferenceFragmentCompat() {
dialog?.dismiss()
}.show()
} else {
Toast.makeText(context, getString(R.string.backup_completed), Toast.LENGTH_SHORT).show()
Toast.makeText(
context,
getString(R.string.backup_completed),
Toast.LENGTH_SHORT
).show()
}
}
}

View File

@@ -27,6 +27,7 @@ import androidx.annotation.DrawableRes
import androidx.core.view.updateLayoutParams
import androidx.databinding.BindingAdapter
import com.google.android.material.elevation.ElevationOverlayProvider
import com.yogeshpaliyal.common.utils.getDrawableOrNull
@BindingAdapter(
"popupElevationOverlay"

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?attr/colorSecondary" android:state_checked="true"/>
<item android:color="@color/color_on_primary_surface_emphasis_medium" />
<item android:color="?attr/colorPrimary" android:state_checked="true"/>
<item android:color="?attr/colorOnSurface" />
</selector>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?attr/colorOnPrimarySurface" android:alpha="0.2" />
<item android:color="?attr/colorOnSurface" android:alpha="0.2" />
</selector>

View File

@@ -14,10 +14,10 @@
android:fillColor="#e6e6e6"/>
<path
android:pathData="M823.272,359.461h33.639v29.733h-33.639z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M823.272,307.996h33.639v29.262h-33.639z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M823.272,359.461h33.639v29.733h-33.639z"
android:fillColor="#fff"/>
@@ -41,10 +41,10 @@
android:fillColor="#e6e6e6"/>
<path
android:pathData="M585.272,359.461h33.639v29.733h-33.639z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M585.272,307.996h33.639v29.262h-33.639z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M585.272,359.461h33.639v29.733h-33.639z"
android:fillColor="#fff"/>
@@ -68,10 +68,10 @@
android:fillColor="#e6e6e6"/>
<path
android:pathData="M315.053,329.181h44.95v39.731h-44.95z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M315.053,260.412h44.95v39.101h-44.95z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M315.053,329.181h44.95v39.731h-44.95z"
android:fillColor="#fff"/>
@@ -86,119 +86,119 @@
android:fillColor="#fff"/>
<path
android:pathData="M0,448.62h963.951v2h-963.951z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M122.773,352.472a29.099,59.374 0,1 0,58.199 0a29.099,59.374 0,1 0,-58.199 0z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M154.559,449.658c-11.655,-69.925 -0.117,-139.598 0.001,-140.293l2.267,0.384c-0.117,0.692 -11.588,69.998 0.001,139.532Z"
android:fillColor="#6c63ff"/>
android:fillColor="?attr/colorTertiaryContainer"/>
<path
android:pathData="M151.178,353.78l26.314,-14.075l1.085,2.028l-26.314,14.075z"
android:fillColor="#6c63ff"/>
android:fillColor="?attr/colorTertiaryContainer"/>
<path
android:pathData="M123.406,348.783l1.085,-2.028l26.311,14.083l-1.085,2.028z"
android:fillColor="#6c63ff"/>
android:fillColor="?attr/colorTertiaryContainer"/>
<path
android:pathData="M25.04,260.903a56.915,116.129 0,1 0,113.83 0a56.915,116.129 0,1 0,-113.83 0z"
android:fillColor="#6c63ff"/>
android:fillColor="?attr/colorTertiaryContainer"/>
<path
android:pathData="M88.295,450.808c-22.765,-136.585 -0.23,-272.673 0.001,-274.032l2.267,0.384c-0.23,1.355 -22.698,137.077 0.001,273.271Z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M81.115,264.43l51.468,-27.529l1.085,2.028l-51.468,27.529z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M26.797,252.719l1.085,-2.028l51.46,27.543l-1.085,2.028z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M138.87,191.008a77.883,158.914 0,1 0,155.767 0a77.883,158.914 0,1 0,-155.767 0z"
android:fillColor="#6c63ff"/>
android:fillColor="?attr/colorTertiaryContainer"/>
<path
android:pathData="M225.847,450.808c-31.14,-186.837 -0.314,-372.992 0.001,-374.851l2.267,0.384c-0.314,1.855 -31.074,187.644 0.001,374.089Z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M215.803,196.207l70.429,-37.671l1.085,2.028l-70.429,37.671z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M141.474,179.435l1.085,-2.028l70.419,37.69l-1.085,2.028z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M841.93,352.472a29.099,59.374 0,1 0,58.199 0a29.099,59.374 0,1 0,-58.199 0z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M868.342,449.658c11.655,-69.925 0.117,-139.598 -0.001,-140.293l-2.267,0.384c0.117,0.692 11.588,69.998 -0.001,139.532Z"
android:fillColor="#6c63ff"/>
android:fillColor="?attr/colorTertiaryContainer"/>
<path
android:pathData="M844.325,341.733l1.085,-2.028l26.314,14.075l-1.085,2.028z"
android:fillColor="#6c63ff"/>
android:fillColor="?attr/colorTertiaryContainer"/>
<path
android:pathData="M872.1,360.838l26.311,-14.083l1.085,2.028l-26.311,14.083z"
android:fillColor="#6c63ff"/>
android:fillColor="?attr/colorTertiaryContainer"/>
<path
android:pathData="M884.031,260.903a56.915,116.129 0,1 0,113.83 0a56.915,116.129 0,1 0,-113.83 0z"
android:fillColor="#6c63ff"/>
android:fillColor="?attr/colorTertiaryContainer"/>
<path
android:pathData="M934.607,450.808c22.765,-136.585 0.23,-272.673 -0.001,-274.032l-2.267,0.384c0.23,1.355 22.698,137.077 -0.001,273.271Z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M889.235,238.928l1.085,-2.028l51.468,27.529l-1.085,2.028z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M943.559,278.235l51.46,-27.543l1.085,2.028l-51.46,27.543z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M728.265,191.008a77.883,158.914 0,1 0,155.767 0a77.883,158.914 0,1 0,-155.767 0z"
android:fillColor="#6c63ff"/>
android:fillColor="?attr/colorTertiaryContainer"/>
<path
android:pathData="M797.055,450.808c31.14,-186.837 0.314,-372.992 -0.001,-374.851l-2.267,0.384c0.314,1.855 31.074,187.644 -0.001,374.089Z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M735.584,160.563l1.085,-2.028l70.429,37.671l-1.085,2.028z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M809.923,215.097l70.419,-37.69l1.085,2.028l-70.419,37.69z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M589.604,101.466l9.206,-7.363c-7.151,-0.789 -10.09,3.111 -11.292,6.198 -5.587,-2.32 -11.669,0.72 -11.669,0.72l18.419,6.687A13.938,13.938 0,0 0,589.604 101.466Z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M364.604,36.466l9.206,-7.363c-7.151,-0.789 -10.09,3.111 -11.292,6.198 -5.587,-2.32 -11.669,0.72 -11.669,0.72l18.419,6.687A13.938,13.938 0,0 0,364.604 36.466Z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M731.604,7.466l9.206,-7.363c-7.151,-0.789 -10.09,3.111 -11.292,6.198 -5.587,-2.32 -11.669,0.72 -11.669,0.72l18.419,6.687A13.938,13.938 0,0 0,731.604 7.466Z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M750.191,437.052a13.918,13.918 0,0 0,-6.97 1.87A14.982,14.982 0,0 0,718.191 450.052h45.95A13.99,13.99 0,0 0,750.191 437.052Z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M283.191,437.052a13.918,13.918 0,0 0,-6.97 1.87A14.982,14.982 0,0 0,251.191 450.052h45.95A13.99,13.99 0,0 0,283.191 437.052Z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M522.191,437.052a13.918,13.918 0,0 0,-6.97 1.87A14.982,14.982 0,0 0,490.191 450.052h45.95A13.99,13.99 0,0 0,522.191 437.052Z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M471.759,404.228l-132.568,0l0,4.276l20.675,0l0,40.626l4.276,0l0,-40.626l80.527,0l0,40.626l4.277,0l0,-40.626l22.813,0l0,-4.276z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M339.452,391.434h132.568v4.276h-132.568z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M339.452,380.743h132.568v4.276h-132.568z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M339.452,370.052h132.568v4.276h-132.568z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M678.759,404.228l-132.568,0l0,4.276l20.675,0l0,40.626l4.276,0l0,-40.626l80.527,0l0,40.626l4.277,0l0,-40.626l22.813,0l0,-4.276z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M546.452,391.434h132.568v4.276h-132.568z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M546.452,380.743h132.568v4.276h-132.568z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
<path
android:pathData="M546.452,370.052h132.568v4.276h-132.568z"
android:fillColor="#3f3d56"/>
android:fillColor="?attr/colorPrimary"/>
</vector>

View File

@@ -93,7 +93,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_anchor="@id/bottomAppBar"
app:srcCompat="@drawable/asl_add_save" />
app:srcCompat="@drawable/asl_add_save"
app:shapeAppearanceOverlay="@style/ShapeAppearance.KeyPass.Cirle"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -1,210 +1,207 @@
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="accountData"
type="com.yogeshpaliyal.keypass.data.AccountModel" />
type="com.yogeshpaliyal.common.data.AccountModel" />
</data>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.core.widget.NestedScrollView
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:fillViewport="true"
android:id="@+id/nestedScrollView"
android:paddingHorizontal="@dimen/grid_0_5"
android:paddingVertical="@dimen/grid_0_5">
android:layout_height="match_parent">
<com.yogeshpaliyal.keypass.custom_views.MaskedCardView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
<androidx.core.widget.NestedScrollView
android:id="@+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="match_parent"
android:fillViewport="true"
android:paddingHorizontal="@dimen/grid_0_5"
android:paddingVertical="@dimen/grid_0_5"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<com.google.android.material.textfield.TextInputLayout
app:layout_constraintTop_toTopOf="@id/topGuideline"
app:layout_constraintStart_toStartOf="@id/startGuideline"
app:layout_constraintEnd_toEndOf="@id/endGuideline"
android:layout_width="0dp"
android:id="@+id/tilAccountName"
android:layout_height="wrap_content"
android:hint="@string/account_name">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etAccountName"
android:singleLine="true"
android:text="@={accountData.title}"
android:inputType="textNoSuggestions|text"
android:layout_width="match_parent"
android:importantForAutofill="no"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_marginTop="@dimen/grid_1"
app:layout_constraintTop_toBottomOf="@id/tilAccountName"
app:layout_constraintStart_toStartOf="@id/startGuideline"
app:layout_constraintEnd_toEndOf="@id/endGuideline"
android:layout_width="0dp"
android:id="@+id/tilUsername"
android:layout_height="wrap_content"
android:hint="@string/username_email_phone">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etUsername"
android:importantForAutofill="no"
android:layout_width="match_parent"
android:singleLine="true"
android:text="@={accountData.username}"
android:inputType="textNoSuggestions|text"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_marginTop="@dimen/grid_1"
app:layout_constraintTop_toBottomOf="@id/tilUsername"
app:layout_constraintStart_toStartOf="@id/startGuideline"
app:layout_constraintEnd_toEndOf="@id/endGuideline"
android:layout_width="0dp"
android:id="@+id/tilPassword"
android:layout_height="wrap_content"
android:hint="@string/password"
app:startIconDrawable="@drawable/ic_round_refresh_24"
app:passwordToggleEnabled="true">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etPassword"
android:importantForAutofill="no"
android:inputType="textNoSuggestions|textPassword"
android:singleLine="true"
android:text="@={accountData.password}"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_marginTop="@dimen/grid_1"
app:layout_constraintTop_toBottomOf="@id/tilPassword"
app:layout_constraintStart_toStartOf="@id/startGuideline"
app:layout_constraintEnd_toEndOf="@id/endGuideline"
android:layout_width="0dp"
android:id="@+id/tilTags"
android:layout_height="wrap_content"
android:hint="@string/tags_comma_separated_optional">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etTag"
android:singleLine="true"
android:importantForAutofill="no"
android:text="@={accountData.tags}"
android:inputType="textNoSuggestions|text"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_marginTop="@dimen/grid_1"
app:layout_constraintTop_toBottomOf="@id/tilTags"
app:layout_constraintStart_toStartOf="@id/startGuideline"
app:layout_constraintEnd_toEndOf="@id/endGuideline"
android:layout_width="0dp"
android:id="@+id/tilWebsite"
android:layout_height="wrap_content"
android:hint="@string/website_url_optional">
<com.google.android.material.textfield.TextInputEditText
android:importantForAutofill="no"
android:id="@+id/etWebsite"
android:inputType="textNoSuggestions|textWebEditText"
android:text="@={accountData.site}"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_marginTop="@dimen/grid_1"
app:layout_constraintTop_toBottomOf="@id/tilWebsite"
app:layout_constraintStart_toStartOf="@id/startGuideline"
app:layout_constraintEnd_toEndOf="@id/endGuideline"
android:layout_width="0dp"
android:id="@+id/tilNotes"
android:layout_height="wrap_content"
android:hint="@string/notes_optional">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etNotes"
android:lines="3"
android:importantForAutofill="no"
android:minLines="3"
android:text="@={accountData.notes}"
android:inputType="textNoSuggestions|text"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
<Space
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="@dimen/grid_1"
app:layout_constraintTop_toBottomOf="@id/tilNotes" />
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/startGuideline"
app:layout_constraintGuide_begin="@dimen/grid_1"
android:orientation="vertical"/>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilAccountName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/account_name"
app:layout_constraintEnd_toEndOf="@id/endGuideline"
app:layout_constraintStart_toStartOf="@id/startGuideline"
app:layout_constraintTop_toTopOf="@id/topGuideline">
<androidx.constraintlayout.widget.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/endGuideline"
app:layout_constraintGuide_end="@dimen/grid_1"
android:orientation="vertical"/>
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etAccountName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAutofill="no"
android:inputType="textNoSuggestions|text"
android:singleLine="true"
android:text="@={accountData.title}" />
</com.google.android.material.textfield.TextInputLayout>
<androidx.constraintlayout.widget.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/topGuideline"
app:layout_constraintGuide_begin="@dimen/grid_1"
android:orientation="horizontal"/>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilUsername"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/grid_1"
android:hint="@string/username_email_phone"
app:layout_constraintEnd_toEndOf="@id/endGuideline"
app:layout_constraintStart_toStartOf="@id/startGuideline"
app:layout_constraintTop_toBottomOf="@id/tilAccountName">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etUsername"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAutofill="no"
android:inputType="textNoSuggestions|text"
android:singleLine="true"
android:text="@={accountData.username}" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilPassword"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/grid_1"
android:hint="@string/password"
app:layout_constraintEnd_toEndOf="@id/endGuideline"
app:layout_constraintStart_toStartOf="@id/startGuideline"
app:layout_constraintTop_toBottomOf="@id/tilUsername"
app:passwordToggleEnabled="true"
app:startIconDrawable="@drawable/ic_round_refresh_24">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAutofill="no"
android:inputType="textNoSuggestions|textPassword"
android:singleLine="true"
android:text="@={accountData.password}" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilTags"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/grid_1"
android:hint="@string/tags_comma_separated_optional"
app:layout_constraintEnd_toEndOf="@id/endGuideline"
app:layout_constraintStart_toStartOf="@id/startGuideline"
app:layout_constraintTop_toBottomOf="@id/tilPassword">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etTag"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAutofill="no"
android:inputType="textNoSuggestions|text"
android:singleLine="true"
android:text="@={accountData.tags}" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilWebsite"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/grid_1"
android:hint="@string/website_url_optional"
app:layout_constraintEnd_toEndOf="@id/endGuideline"
app:layout_constraintStart_toStartOf="@id/startGuideline"
app:layout_constraintTop_toBottomOf="@id/tilTags">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etWebsite"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAutofill="no"
android:inputType="textNoSuggestions|textWebEditText"
android:singleLine="true"
android:text="@={accountData.site}" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilNotes"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/grid_1"
android:hint="@string/notes_optional"
app:layout_constraintEnd_toEndOf="@id/endGuideline"
app:layout_constraintStart_toStartOf="@id/startGuideline"
app:layout_constraintTop_toBottomOf="@id/tilWebsite">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etNotes"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAutofill="no"
android:inputType="textNoSuggestions|text"
android:lines="3"
android:minLines="3"
android:text="@={accountData.notes}" />
</com.google.android.material.textfield.TextInputLayout>
<Space
android:layout_width="match_parent"
android:layout_height="@dimen/grid_1"
app:layout_constraintTop_toBottomOf="@id/tilNotes" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.Guideline
android:id="@+id/startGuideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="@dimen/grid_1" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/endGuideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_end="@dimen/grid_1" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/topGuideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="@dimen/grid_1" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.yogeshpaliyal.keypass.custom_views.MaskedCardView>
</androidx.core.widget.NestedScrollView>
</androidx.core.widget.NestedScrollView>
<com.google.android.material.bottomappbar.BottomAppBar
android:id="@+id/bottomAppBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:fabAlignmentMode="end"
app:hideOnScroll="true"
app:fabCradleRoundedCornerRadius="@dimen/bottom_app_bar_fab_cradle_corner_radius"
app:fabCradleMargin="@dimen/bottom_app_bar_fab_cradle_margin"
app:navigationIcon="@drawable/ic_baseline_arrow_back_ios_24"/>
<com.google.android.material.bottomappbar.BottomAppBar
android:id="@+id/bottomAppBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:fabAlignmentMode="end"
app:fabCradleMargin="@dimen/bottom_app_bar_fab_cradle_margin"
app:fabCradleRoundedCornerRadius="@dimen/bottom_app_bar_fab_cradle_corner_radius"
app:hideOnScroll="true"
app:navigationIcon="@drawable/ic_baseline_arrow_back_ios_24"
app:navigationIconTint="?attr/colorOnSurface" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_round_done_24"
android:layout_marginEnd="@dimen/grid_2"
app:layout_anchor="@id/bottomAppBar"
android:id="@+id/btnSave"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btnSave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/grid_2"
app:layout_anchor="@id/bottomAppBar"
app:shapeAppearanceOverlay="@style/ShapeAppearance.KeyPass.Cirle"
app:srcCompat="@drawable/ic_round_done_24" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>

View File

@@ -3,14 +3,14 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="com.yogeshpaliyal.keypass.data.AccountModel" />
<import type="com.yogeshpaliyal.keypass.data.MyAccountModel" />
<variable
name="model"
type="AccountModel" />
type="MyAccountModel" />
<variable
name="listener"
type="com.yogeshpaliyal.keypass.listener.AccountsClickListener&lt;AccountModel>" />
type="com.yogeshpaliyal.keypass.listener.AccountsClickListener&lt;MyAccountModel>" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
@@ -27,7 +27,9 @@
android:elevation="@dimen/plane_00"
android:clickable="true"
android:focusable="true"
app:cardElevation="0dp"
app:cardElevation="1dp"
app:strokeWidth="0dp"
app:layout_constraintBottom_toBottomOf="parent"
android:onClick="@{(view)->listener.onItemClick(view, model)}"
android:layout_marginVertical="@dimen/grid_0_25"
android:layout_marginHorizontal="@dimen/grid_0_5">

View File

@@ -3,14 +3,14 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="com.yogeshpaliyal.keypass.data.AccountModel" />
<import type="com.yogeshpaliyal.keypass.data.MyAccountModel" />
<variable
name="model"
type="AccountModel" />
type="MyAccountModel" />
<variable
name="listener"
type="com.yogeshpaliyal.keypass.listener.AccountsClickListener&lt;AccountModel>" />
type="com.yogeshpaliyal.keypass.listener.AccountsClickListener&lt;MyAccountModel>" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
@@ -25,12 +25,14 @@
app:layout_constraintEnd_toEndOf="parent"
app:cardUseCompatPadding="true"
android:elevation="@dimen/plane_00"
app:cardElevation="0dp"
app:cardElevation="1dp"
app:strokeWidth="0dp"
android:clickable="true"
android:focusable="true"
android:onClick="@{(view)->listener.onItemClick(view, model)}"
android:layout_marginVertical="@dimen/grid_0_25"
android:layout_marginHorizontal="@dimen/grid_0_5">
android:layout_marginHorizontal="@dimen/grid_0_5"
app:layout_constraintBottom_toBottomOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@@ -29,7 +29,7 @@
android:layout_marginHorizontal="@dimen/grid_4"
android:text="@{navDivider.title}"
android:textAppearance="?attr/textAppearanceOverline"
android:textColor="@color/color_on_primary_surface_emphasis_medium"
android:textColor="?attr/colorOnSurface"
android:drawablePadding="@dimen/grid_4"
app:drawableTopCompat="@drawable/nav_divider_top" />

View File

@@ -33,16 +33,15 @@
android:layout_height="@dimen/navigation_drawer_menu_item_height"
android:paddingLeft="@dimen/grid_4"
android:paddingRight="@dimen/grid_4"
android:background="?attr/selectableItemBackground"
android:gravity="center_vertical|start"
android:onClick="@{() -> navListener.onNavEmailFolderClicked(navEmailFolder)}"
android:ellipsize="end"
android:lines="1"
android:text="@{navEmailFolder.category}"
android:textColor="@color/color_on_primary_surface_emphasis_medium"
android:textColor="?attr/colorOnSurface"
android:textAppearance="?attr/textAppearanceSubtitle1"
app:drawableStartCompat="@drawable/ic_twotone_folder"
app:drawableTint="@color/color_on_primary_surface_emphasis_medium"
app:drawableTint="?attr/colorOnSurface"
android:drawablePadding="@dimen/grid_4"
tools:text="Pine Elementary" />

View File

@@ -32,7 +32,6 @@
android:layout_height="@dimen/navigation_drawer_menu_item_height"
android:paddingLeft="@dimen/grid_4"
android:paddingRight="@dimen/grid_4"
android:background="?attr/selectableItemBackground"
android:gravity="center_vertical|start"
android:onClick="@{() -> navListener.onNavMenuItemClicked(navMenuItem)}"
android:ellipsize="end"

View File

@@ -1,12 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.KeyPass" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<style name="Theme.KeyPass" parent="Theme.Material3.Dark.NoActionBar">
<!--Color-->
<item name="colorPrimary">@color/keypass_blue_200</item>
<item name="colorPrimaryVariant">@color/keypass_blue_300</item>
<item name="colorSecondary">@color/keypass_orange_300</item>
<item name="colorSecondaryVariant">@color/keypass_orange_300</item>
<item name="colorPrimaryContainer">@color/keypass_orange_300</item>
<item name="colorTertiaryContainer">@color/blue_800</item>
<item name="android:colorBackground">@color/keypass_black_900</item>
<item name="colorSurface">@color/keypass_black_800</item>
<item name="colorPrimarySurfaceVariant">?attr/colorSurface</item>

View File

@@ -12,6 +12,7 @@
<color name="keypass_blue_600">#4a6572</color>
<color name="keypass_blue_700">#344955</color>
<color name="keypass_blue_800">#232f34</color>
<color name="blue_800">#6c63ff</color>
<color name="keypass_orange_300">#fbd790</color>
<color name="keypass_orange_400">#f9be64</color>
@@ -34,4 +35,7 @@
<!--handles contrast by either dynamically coloring the nav bar handle (gesture nav) -->
<!--or automatically applying a translucent background (3-button mode).-->
<color name="nav_bar">@color/keypass_black_900_alpha_020</color>
</resources>

View File

@@ -23,4 +23,9 @@
<dimen name="keypass_medium_component_corner_radius">0dp</dimen>
<dimen name="keypass_large_component_corner_radius">12dp</dimen>
<style name="ShapeAppearance.KeyPass.Cirle" parent="">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">50%</item>
</style>
</resources>

View File

@@ -1,8 +1,10 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.KeyPass" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<style name="Theme.KeyPass" parent="Theme.Material3.Light.NoActionBar">
<!--Color-->
<item name="colorPrimary">@color/keypass_blue_700</item>
<item name="colorPrimaryContainer">@color/keypass_orange_500</item>
<item name="colorTertiaryContainer">@color/blue_800</item>
<item name="colorPrimaryVariant">@color/keypass_blue_800</item>
<item name="colorSecondary">@color/keypass_orange_500</item>
<item name="colorSecondaryVariant">@color/keypass_orange_400</item>
@@ -52,7 +54,6 @@
<item name="motionInterpolatorOutgoing">@android:interpolator/accelerate_cubic</item>
<!--Styles-->
<item name="bottomAppBarStyle">@style/Widget.MaterialComponents.BottomAppBar.PrimarySurface</item>
<item name="bottomSheetStyle">@style/Widget.MaterialComponents.BottomSheet.Modal</item>
<item name="navigationViewStyle">@style/Widget.KeyPass.NavigationView</item>
<item name="chipStyle">@style/Widget.KeyPass.Chip.Entry</item>

View File

@@ -2,11 +2,12 @@
buildscript {
ext{
kotlin_version = "1.5.31"
lifecycle_version = "2.3.1"
kotlin_version = "1.5.21"
lifecycle_version = "2.4.0"
room_version = "2.3.0"
navigation_version = '2.3.5'
ext.hilt_version = '2.38.1'
ext.hilt_version = '2.40'
compose_version = '1.0.1'
}
repositories {
@@ -14,7 +15,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.2'
classpath 'com.android.tools.build:gradle:7.0.4'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.10'
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigation_version"
@@ -22,20 +23,20 @@ buildscript {
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
plugins {
id 'com.diffplug.spotless' version '5.10.2'
id 'com.diffplug.spotless' version '6.0.4'
}
allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
mavenCentral()
}
}

1
common/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

72
common/build.gradle Normal file
View File

@@ -0,0 +1,72 @@
plugins {
id 'com.android.library'
id 'kotlin-android'
id 'kotlin-kapt'
id("dagger.hilt.android.plugin")
}
android {
compileSdk 31
defaultConfig {
minSdk 21
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.0'
implementation 'com.google.android.material:material:1.6.0-alpha01'
implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
// apache common codec
implementation "commons-codec:commons-codec:1.15"
//Androidx Security
implementation "androidx.security:security-crypto:1.1.0-alpha03"
implementation "androidx.room:room-runtime:$room_version"
androidTestImplementation 'androidx.test:rules:1.4.0'
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
// dependency injection
implementation("com.google.dagger:hilt-android:$hilt_version")
kapt("com.google.dagger:hilt-android-compiler:$hilt_version")
implementation("androidx.hilt:hilt-work:1.0.0")
// When using Kotlin.
kapt("androidx.hilt:hilt-compiler:1.0.0")
implementation "androidx.work:work-runtime-ktx:2.7.1"
implementation 'com.google.code.gson:gson:2.8.9'
}

21
common/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@@ -0,0 +1,19 @@
package com.yogeshpaliyal.common
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Assert.*
import org.junit.Test
import org.junit.runner.RunWith
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
}
}

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yogeshpaliyal.common">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.KeyPass">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -1,8 +1,8 @@
package com.yogeshpaliyal.keypass
package com.yogeshpaliyal.common
import androidx.room.Database
import androidx.room.RoomDatabase
import com.yogeshpaliyal.keypass.data.AccountModel
import com.yogeshpaliyal.common.data.AccountModel
import com.yogeshpaliyal.keypass.db.DbDao
/*
@@ -20,5 +20,4 @@ abstract class AppDatabase : RoomDatabase() {
// define DAO start
abstract fun getDao(): DbDao
// define DAO end
}

View File

@@ -0,0 +1,11 @@
package com.yogeshpaliyal.common
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}

View File

@@ -1,16 +1,12 @@
package com.yogeshpaliyal.keypass.data
package com.yogeshpaliyal.common.data
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.google.gson.Gson
import com.google.gson.annotations.SerializedName
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.common.utils.TOTPHelper
import com.yogeshpaliyal.common.utils.getRandomString
import com.yogeshpaliyal.keypass.constants.AccountType
import com.yogeshpaliyal.keypass.utils.TOTPHelper
import com.yogeshpaliyal.keypass.utils.getRandomString
import com.yogeshpaliyal.universal_adapter.listener.UniversalViewType
import com.yogeshpaliyal.universal_adapter.model.BaseDiffUtil
/*
* @author Yogesh Paliyal
@@ -19,7 +15,7 @@ import com.yogeshpaliyal.universal_adapter.model.BaseDiffUtil
* created on 30-01-2021 20:38
*/
@Entity(tableName = "account")
data class AccountModel(
open class AccountModel(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
@SerializedName("id")
@@ -57,28 +53,14 @@ data class AccountModel(
@ColumnInfo(name = "type")
@SerializedName("type")
var type: Int? = AccountType.DEFAULT
) : BaseDiffUtil, UniversalViewType {
) {
fun getInitials() = (
title?.firstOrNull() ?: username?.firstOrNull() ?: site?.firstOrNull()
?: notes?.firstOrNull() ?: 'K'
).toString()
override fun getDiffId(): Any? {
return id
}
override fun getDiffBody(): Any? {
return if (type == AccountType.TOTP) {
super.getDiffBody()
} else {
Gson().toJson(this)
}
}
fun getOtp() = TOTPHelper.generate(password)
fun getTOtpProgress() = TOTPHelper.getProgress().toInt()
override fun getLayoutId(): Int = if (type == AccountType.TOTP) R.layout.item_totp else R.layout.item_accounts
}

View File

@@ -1,4 +1,4 @@
package com.yogeshpaliyal.keypass.data
package com.yogeshpaliyal.common.data
import com.google.gson.annotations.Expose
import com.google.gson.annotations.SerializedName

View File

@@ -1,4 +1,4 @@
package com.yogeshpaliyal.keypass.data
package com.yogeshpaliyal.common.data
import androidx.recyclerview.widget.DiffUtil

View File

@@ -2,7 +2,7 @@ package com.yogeshpaliyal.keypass.db
import androidx.lifecycle.LiveData
import androidx.room.*
import com.yogeshpaliyal.keypass.data.AccountModel
import com.yogeshpaliyal.common.data.AccountModel
import kotlinx.coroutines.flow.Flow
/*

View File

@@ -1,13 +1,14 @@
package com.yogeshpaliyal.keypass.db_helper
package com.yogeshpaliyal.common.db_helper
import android.content.ContentResolver
import android.net.Uri
import androidx.room.withTransaction
import com.google.gson.Gson
import com.yogeshpaliyal.keypass.AppDatabase
import com.yogeshpaliyal.common.AppDatabase
import com.yogeshpaliyal.common.data.BackupData
import com.yogeshpaliyal.common.utils.getRandomString
import com.yogeshpaliyal.keypass.constants.AccountType
import com.yogeshpaliyal.keypass.data.BackupData
import com.yogeshpaliyal.keypass.utils.getRandomString
import com.yogeshpaliyal.keypass.db_helper.EncryptionHelper
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.withContext
@@ -19,13 +20,17 @@ import kotlinx.coroutines.withContext
* created on 20-02-2021 19:31
*/
suspend fun AppDatabase.createBackup(key: String, contentResolver: ContentResolver, fileUri: Uri?) =
suspend fun AppDatabase.createBackup(
key: String,
contentResolver: ContentResolver,
fileUri: Uri?
) =
withContext(Dispatchers.IO) {
fileUri ?: return@withContext false
val data = getDao().getAllAccountsList()
data ?: return@withContext false
val json = Gson().toJson(BackupData(this@createBackup.openHelper.readableDatabase.version, data))
val json =
Gson().toJson(BackupData(this@createBackup.openHelper.readableDatabase.version, data))
val fileStream = contentResolver.openOutputStream(fileUri)
EncryptionHelper.doCryptoEncrypt(key, json, fileStream)
@@ -49,7 +54,7 @@ suspend fun AppDatabase.restoreBackup(
return@withContext Gson().fromJson(restoredFile, BackupData::class.java)?.let { data ->
if (data.version == 3) {
for (datum in data.data) {
datum.uniqueId = getRandomString()
getRandomString().also { datum.uniqueId = it }
}
}
if (data.version < 5) {

View File

@@ -1,14 +1,14 @@
package com.yogeshpaliyal.keypass.di.module
package com.yogeshpaliyal.common.di.module
import android.content.Context
import android.content.SharedPreferences
import androidx.room.Room
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import com.yogeshpaliyal.keypass.AppDatabase
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.utils.MySharedPreferences
import com.yogeshpaliyal.keypass.utils.getRandomString
import com.yogeshpaliyal.common.AppDatabase
import com.yogeshpaliyal.common.R
import com.yogeshpaliyal.common.utils.MySharedPreferences
import com.yogeshpaliyal.common.utils.getRandomString
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.yogeshpaliyal.keypass.utils
package com.yogeshpaliyal.common.utils
import androidx.annotation.ColorInt
import androidx.annotation.FloatRange

View File

@@ -1,4 +1,4 @@
package com.yogeshpaliyal.keypass.utils
package com.yogeshpaliyal.common.utils
import android.content.Context
import android.view.autofill.AutofillManager

View File

@@ -1,12 +1,12 @@
package com.yogeshpaliyal.keypass.utils
package com.yogeshpaliyal.common.utils
import android.content.Context
import android.content.SharedPreferences
import android.net.Uri
import android.text.TextUtils
import androidx.documentfile.provider.DocumentFile
import com.yogeshpaliyal.keypass.AppDatabase
import com.yogeshpaliyal.keypass.db_helper.createBackup
import com.yogeshpaliyal.common.AppDatabase
import com.yogeshpaliyal.common.db_helper.createBackup
import java.security.SecureRandom
/*

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.yogeshpaliyal.keypass.utils
package com.yogeshpaliyal.common.utils
import android.annotation.SuppressLint
import android.content.Context

View File

@@ -1,4 +1,4 @@
package com.yogeshpaliyal.keypass.utils
package com.yogeshpaliyal.common.utils
import java.text.SimpleDateFormat
import java.util.*

View File

@@ -1,4 +1,4 @@
package com.yogeshpaliyal.keypass.utils
package com.yogeshpaliyal.common.utils
/*Used as a wrapper for data that is exposed via a LiveData that represents an
event.*/

View File

@@ -1,4 +1,4 @@
package com.yogeshpaliyal.keypass.utils
package com.yogeshpaliyal.common.utils
import android.content.Context
import android.content.Intent

View File

@@ -1,4 +1,4 @@
package com.yogeshpaliyal.keypass.utils
package com.yogeshpaliyal.common.utils
import android.content.Context
import android.security.keystore.KeyGenParameterSpec

View File

@@ -1,4 +1,4 @@
package com.yogeshpaliyal.keypass.utils
package com.yogeshpaliyal.common.utils
class PasswordGenerator(
private var length: Int,
@@ -28,12 +28,13 @@ class PasswordGenerator(
list.add(SYMBOLS)
for (i in 1..length) {
val choice = list.random()
when (choice) {
UPPER_CASE -> password += ('A'..'Z').random().toString()
LOWER_CASE -> password += ('a'..'z').random().toString()
NUMBERS -> password += ('0'..'9').random().toString()
SYMBOLS -> password += listOf('!', '@', '#', '$', '%', '&', '*', '+', '=', '-', '~', '?', '/', '_').random().toString()
if (list.isNotEmpty()) {
when (list.random()) {
UPPER_CASE -> password += ('A'..'Z').random().toString()
LOWER_CASE -> password += ('a'..'z').random().toString()
NUMBERS -> password += ('0'..'9').random().toString()
SYMBOLS -> password += listOf('!', '@', '#', '$', '%', '&', '*', '+', '=', '-', '~', '?', '/', '_').random().toString()
}
}
}
return password

View File

@@ -1,4 +1,4 @@
package com.yogeshpaliyal.keypass.utils
package com.yogeshpaliyal.common.utils
import android.content.SharedPreferences
import androidx.core.content.edit

View File

@@ -1,4 +1,4 @@
package com.yogeshpaliyal.keypass.utils
package com.yogeshpaliyal.common.utils
import java.util.*

View File

@@ -1,4 +1,4 @@
package com.yogeshpaliyal.keypass.utils;
package com.yogeshpaliyal.common.utils;
import android.net.Uri;

View File

@@ -1,4 +1,4 @@
package com.yogeshpaliyal.keypass.utils;
package com.yogeshpaliyal.common.utils;
import org.apache.commons.codec.binary.Hex;

View File

@@ -1,4 +1,4 @@
package com.yogeshpaliyal.keypass.utils;
package com.yogeshpaliyal.common.utils;
import android.content.Context;
import android.content.res.Resources;

View File

@@ -6,11 +6,11 @@ import android.net.Uri
import androidx.hilt.work.HiltWorker
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import com.yogeshpaliyal.keypass.AppDatabase
import com.yogeshpaliyal.keypass.utils.backupAccounts
import com.yogeshpaliyal.keypass.utils.canUserAccessBackupDirectory
import com.yogeshpaliyal.keypass.utils.getBackupDirectory
import com.yogeshpaliyal.keypass.utils.overrideAutoBackup
import com.yogeshpaliyal.common.AppDatabase
import com.yogeshpaliyal.common.utils.backupAccounts
import com.yogeshpaliyal.common.utils.canUserAccessBackupDirectory
import com.yogeshpaliyal.common.utils.getBackupDirectory
import com.yogeshpaliyal.common.utils.overrideAutoBackup
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import kotlinx.coroutines.Dispatchers

View File

@@ -1,11 +1,12 @@
package com.yogeshpaliyal.keypass.worker
package com.yogeshpaliyal.common.worker
import android.content.Context
import android.content.SharedPreferences
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import com.yogeshpaliyal.keypass.utils.isAutoBackupEnabled
import com.yogeshpaliyal.common.utils.isAutoBackupEnabled
import com.yogeshpaliyal.keypass.worker.AutoBackupWorker
fun Context?.executeAutoBackup(sp: SharedPreferences) {
this ?: return

View File

@@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View File

@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.KeyPass" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">common</string>
</resources>

View File

@@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.KeyPass" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

View File

@@ -0,0 +1,16 @@
package com.yogeshpaliyal.common
import org.junit.Assert.*
import org.junit.Test
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

View File

@@ -0,0 +1,2 @@
Now supports Material YOU
Crash fix in Generate password

1
keypasscompose/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,68 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
}
android {
compileSdk 31
defaultConfig {
applicationId "com.yogeshpaliyal.keypasscompose"
minSdk 21
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary true
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
useIR = true
}
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion compose_version
kotlinCompilerVersion '1.5.21'
}
packagingOptions {
resources {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
}
}
dependencies {
implementation project(":common")
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.0'
implementation 'com.google.android.material:material:1.6.0-alpha01'
implementation "androidx.compose.ui:ui:1.1.0-beta02"
implementation "androidx.compose.material:material:1.0.5"
implementation "androidx.compose.ui:ui-tooling-preview:1.0.5"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0'
implementation 'androidx.activity:activity-compose:1.4.0'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:1.0.5"
debugImplementation "androidx.compose.ui:ui-tooling:1.0.5"
implementation 'androidx.compose.material3:material3:1.0.0-alpha02'
}

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