diff --git a/.github/ISSUE_TEMPLATE/feedback---question---help-wanted.md b/.github/ISSUE_TEMPLATE/feedback---question---help-wanted.md index 5186aa09..b57eec62 100644 --- a/.github/ISSUE_TEMPLATE/feedback---question---help-wanted.md +++ b/.github/ISSUE_TEMPLATE/feedback---question---help-wanted.md @@ -21,7 +21,8 @@ describe in short paragraph, what you are write or what question or concern you ## Thoughts -describe your thought and feedback related to app. if you have question then delete this section and fill the question section... +describe your thought and feedback related to app. if you have question then delete this section and +fill the question section... ## Question diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ea606a64..ad7a9833 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,6 +9,7 @@ updates: directory: "/" # Location of package manifests schedule: day: "sunday" + interval: "weekly" target-branch: "jeel-dev" assignees: - "JeelDobariya38" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 7e64e384..a8f8245b 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -4,16 +4,16 @@ - summary 2. - ... -> Summary here, should be in one line (write consise so that reviewer without take look at code, can say/determine what changed).. -> summary above should provide structure overview that one can read and understand what changed. +> Summary here, should be in one line (write concisely so that reviewer without take look at code, can +> say/determine what changed).. +> summary above should provide structure overview that one can read and understand what changed. > summary should not be a detail guide, just short description. -> you can provide further infomation in notes section or it would be expictily ask in pr comments at time of review if need..) - +> you can provide further information in notes section or it would be explicitly ask in pr comments at +> time of review if need..) # Breaking Changes -- [Write about any breaking changes, like architecture changes or database changes etc.. If none, remove the section compeletly]. - +- [Write about any breaking changes, like architecture changes or database changes etc.. If none, remove the section completely]. ## Notes diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 052bbde5..6fe2208c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -22,7 +22,7 @@ on: - 'docs/**' release: - types: [created, published] + types: [ created, published ] jobs: analyze: diff --git a/README.md b/README.md index b6b8de81..16f69454 100644 --- a/README.md +++ b/README.md @@ -2,31 +2,36 @@ > [!WARNING] > It is just a open source project. An is current under active development. -> Please, consider using it for fun, and not for real password managment. (untill, we offically release a stable release) +> Please, consider using it for fun, and not for real password management. (until, we officially +> release a stable release)
- + passcodes play store banner - + ![Static Badge](https://img.shields.io/badge/Release-Prototype-blue) [![Android CI/CD](https://github.com/PasscodesApp/Passcodes/actions/workflows/build-apks.yml/badge.svg)](https://github.com/PasscodesApp/Passcodes/actions/workflows/build-apks.yml) ![Visitor Counter (@hehuapei/visitor-badge)](https://visitor-badge.laobi.icu/badge?page_id=JeelDobariya38.Passcodes&format=true)
-A android app that take down the headache of remembering passwords. It is open source solutions that help you in keeping your passwords safe and secure, in your own local storage without ever needing to push them to cloud. +A android app that take down the headache of remembering passwords. It is open source solutions that +help you in keeping your passwords safe and secure, in your own local storage without ever needing +to push them to cloud. > What we think of passcodes? -> Password management is one such thing that is as simple as remember a password yet, it very important topic in term of security. So, we as developer of passcodes think to streamline and securing the process as much as possible. [Read more](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/other-docs/project-overview.md) +> Password management is one such thing that is as simple as remember a password yet, it very +> important topic in term of security. So, we as developer of passcodes think to streamline and +> securing the process as much as +> possible. [Read more](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/other-docs/project-overview.md) ## Website -[Vist Website](https://jeeldobariya38.github.io/Passcodes-Website/) +[Visit Website](https://jeeldobariya38.github.io/Passcodes-Website/) ## Screen Shots -
- View Here +
@@ -46,24 +51,25 @@ Note: high version can still run, but are not guaranteed offically. ## Features -- [x] Intuitive UI. +- [ ] Intuitive UI. - [ ] Update Checkers & Manager. - [x] Password Management. (Current Priority) -- [ ] Secure File. (Least Priority, Because it include permission. Which, I am as developer not familar with 😂) +- [ ] Secure File. (Least Priority, Because it include permission. Which, I am as developer not + familiar with 😂) - Could be Image. (JPG. PNG ....) - - Could be Vidoe. + - Could be Video. - Could any Binary File. (more like won't be a text file) - [ ] Other Secret Info Management. - Could be note. (txt file) - Could be any info that can encode as key & value. -```json -{ - "key": "SECRET API KEY", - "content": "qwerty-let-say", - "createdat": "...", - "updatedat": "..." -} -``` + ```json + { + "key": "SECRET API KEY", + "content": "qwerty-let-say", + "created-at": "...", + "updated-at": "..." + } + ``` - [ ] NON Secret Info Store. - [ ] Encryption and Decryption. - [ ] Backup Manager. @@ -76,13 +82,18 @@ Note: high version can still run, but are not guaranteed offically. ## Installation Steps -1. Go to our [github repository release page](https://github.com/PasscodesApp/Passcodes/releases/latest). +1. Go to + our [github repository release page](https://github.com/PasscodesApp/Passcodes/releases/latest). -2. Download the apk for your phone. If Don't know the architecture of phone then download apk file that has universal in its name. +2. Download the apk for your phone. If Don't know the architecture of phone then download apk file + that has universal in its name. 3. Install the apk and you are ready to use the app. -It was most shortest and sweetest description (I have ever crafted), For more detailed description, Vist the file [installing.md](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/user-docs/installing.md) in `PasscodesApp/Passcodes-Docs`. +It was most shortest and sweetest description (I have ever crafted), For more detailed description, +See the +file [installing.md](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/user-docs/installing.md) +in `PasscodesApp/Passcodes-Docs`. ## Building The App @@ -92,39 +103,58 @@ It was most shortest and sweetest description (I have ever crafted), For more de 3. Follow the general step and build the app. -4. For code documention and support docs, check the `docs/` folder in our repository. +4. For code documentation and support docs, check the `docs/` folder in our repository. -It was general, intuitive, short and sweet description, For more detailed description, Vist the file [building.md](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/dev-docs/building.md) in `PasscodesApp/Passcodes-Docs`. +It was general, intuitive, short and sweet description, For more detailed description, Visit the +file [building.md](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/dev-docs/building.md) in +`PasscodesApp/Passcodes-Docs`. ## Support Docs -You can checkout support docs, provided in [PasscodesApp/Passcodes-Docs](https://github.com/PasscodesApp/Passcodes-Docs) Or You can even seek help on our [telegram community](https://t.me/passcodescommunity) +You can checkout support docs, provided +in [PasscodesApp/Passcodes-Docs](https://github.com/PasscodesApp/Passcodes-Docs) Or You can even +seek help on our [telegram community](https://t.me/passcodescommunity) ## Changelog & Release Notes -- Professional ChangeLog: [here](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/user-docs/changelog.md) -- Casual Release Notes: [here](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/user-docs/release-notes.md) +- Professional + ChangeLog: [here](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/user-docs/changelog.md) +- Casual Release + Notes: [here](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/user-docs/release-notes.md) ## Contribution Are Appreciated!!! > [!IMPORTANT] > Currently the project (more or less also me) is not ready for (code) contributions. -> This project is currently limited by my expertise & I am beginner. Meaning I don;t want others code in my codebase, that I don't understand, I am learning android and will surely learn basic off by start of 2026.. then i will allow the contibution to this repo... But as of now i don't admire code contribution. As I am beginner in android and might have difficuly understand code that not written by me... +> This project is currently limited by my expertise & I am beginner. Meaning I don;t want others +> code in my codebase, that I don't understand, I am learning android and will surely learn basic +> off by start of 2026.. then i will allow the contribution to this repo... But as of now i don't +> admire code contribution. As I am beginner in android and might have difficultly in understanding +> code that not written by me... > -> There are still other ways to contribute to project.. like by testing app, by contributing to documenation or more or less just by spreading the word around.. about the app. but, code contribution is limited from my side.... & I hope you can understand... +> There are still other ways to contribute to project.. like by testing app, by contributing to +> documentation or more or less just by spreading the word around.. about the app. but, code +> contribution is limited from my side.... & I hope you can understand... > -> For more, infomation on what kind of contribtuion we approve or allow, please open a issue in our repo. that way you avoid wasteing your time... +> For more, information on what kind of contribution we approve or allow, please open a issue in our +> repo. that way you avoid wasting your time... > > [Read More](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/other-docs/open-contributing-timeline.md) -By, contributing to project you accept the [Terms For Contributions](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/other-docs/terms-for-contributions.md), [CONTRIBUTING.md](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/CONTRIBUTING.md) & [MIT License](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/LICENSE.txt). +By, contributing to project you accept +the [Terms For Contributions](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/other-docs/terms-for-contributions.md), [CONTRIBUTING.md](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/CONTRIBUTING.md) & [MIT License](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/LICENSE.txt). -And also have look at [Open Contributing Timeline](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/other-docs/open-contributing-timeline.md). +And also have look +at [Open Contributing Timeline](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/other-docs/open-contributing-timeline.md). ## Security Policy -Avaliable here in [PasscodesApp/Passcodes-Docs](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/SECURITY.md). +Available here +in [PasscodesApp/Passcodes-Docs](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/SECURITY.md). ## License -Passcodes Project is license under [MIT](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/LICENSE.txt) License. Downloading Or Use the app or any associated stuff would mean, you are okay and have accepted the license terms. +Passcodes Project is license +under [MIT](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/LICENSE.txt) License. +Downloading Or Use the app or any associated stuff would mean, you are okay and have accepted the +license terms. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 91cd641c..211192fd 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,14 +1,56 @@ -import java.io.FileInputStream -import java.util.Properties // import org.gradle.api.GradleException import com.android.build.api.dsl.ApplicationExtension import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import java.io.FileInputStream +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale +import java.util.Properties + +/** + * Gets the current system time formatted as 'yy-mm-dd : hh-mm-ss'. + */ +fun getCurrentTimeLabel(): String { + val formatter = SimpleDateFormat("yy-MM-dd : HH-mm-ss", Locale.getDefault()) + return formatter.format(Date()) +} + +// -------------------------------------------------------------------------------- +// | 🚀 BUILD CONFIGURATION PROPERTIES: UPDATE VERSIONS AND NAMES HERE ONLY | +// -------------------------------------------------------------------------------- + + +// Core Versioning +val appVersionCode = 3 +val appVersionName = "v1.1.2-Alpha" +val appLabel = "v1.1.2 - Alpha" +val appDevLabel = "v1.1.2 - ${getCurrentTimeLabel()}" + +// SDK Versions +val appCompileSdk = 36 +val appMinSdk = 26 +val appTargetSdk = 34 + +// Naming & Identification +val appNamespace = "com.jeeldobariya.passcodes" +val appBaseName = "Passcodes" + +// Icon Configuration +val mainIcon = "@mipmap/ic_launcher" +val mainRoundIcon = "@mipmap/ic_launcher_round" +val devIcon = "@mipmap/dev_ic_launcher" +val devRoundIcon = "@mipmap/dev_ic_launcher_round" + + +// -------------------------------------------------------------------------------- +// | ⚙️ PLUGINS AND CONFIGURATION | +// -------------------------------------------------------------------------------- + plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.compose) - alias(libs.plugins.jetbrains.kotlin.serialization) alias(libs.plugins.ksp) alias(libs.plugins.oss.licenses) } @@ -21,15 +63,17 @@ kotlin { android { (this as ApplicationExtension).apply { - compileSdk = 36 - namespace = "com.jeeldobariya.passcodes" + compileSdk = appCompileSdk + namespace = appNamespace defaultConfig { - applicationId = "com.jeeldobariya.passcodes" - minSdk = 26 - targetSdk = 34 - versionCode = 2 - versionName = "v1.1.2-rc.2" + applicationId = appNamespace + minSdk = appMinSdk + targetSdk = appTargetSdk + versionCode = appVersionCode + + // WARN: Keep it consistent with the res value property in build variants below... + versionName = appVersionName testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } @@ -94,23 +138,16 @@ android { isDebuggable = false isShrinkResources = true isMinifyEnabled = true - proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") - - // Use manifestPlaceholders.put() for key-value pairs - manifestPlaceholders["appIcon"] = "@mipmap/ic_launcher" - manifestPlaceholders["appLabel"] = "@string/app_name" - } + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) - getByName("debug") { - applicationIdSuffix = ".dev" - versionNameSuffix = "-Dev" + resValue("string", "app_name", appBaseName) + resValue("string", "app_version", appLabel) - isDebuggable = true - isShrinkResources = false - isMinifyEnabled = false - - manifestPlaceholders["appIcon"] = "@mipmap/dev_ic_launcher" - manifestPlaceholders["appLabel"] = "Passcodes-Dev" + manifestPlaceholders["appIcon"] = mainIcon + manifestPlaceholders["appRoundIcon"] = mainRoundIcon } create("staging") { @@ -127,10 +164,31 @@ android { isDebuggable = false isShrinkResources = true isMinifyEnabled = true - proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + + resValue("string", "app_name", "$appBaseName Staging") + resValue("string", "app_version", appDevLabel) - manifestPlaceholders["appIcon"] = "@mipmap/dev_ic_launcher" - manifestPlaceholders["appLabel"] = "Passcodes-Staging" + manifestPlaceholders["appIcon"] = devIcon + manifestPlaceholders["appRoundIcon"] = devRoundIcon + } + + getByName("debug") { + applicationIdSuffix = ".dev" + versionNameSuffix = "-Dev" + + isDebuggable = true + isShrinkResources = false + isMinifyEnabled = false + + resValue("string", "app_name", "$appBaseName Debug") + resValue("string", "app_version", appDevLabel) + + manifestPlaceholders["appIcon"] = devIcon + manifestPlaceholders["appRoundIcon"] = devRoundIcon } } } @@ -145,64 +203,35 @@ android { buildConfig = true compose = true } - - ksp { - val location = "$projectDir/schemas" - arg("room.schemaLocation", location) - } } dependencies { + // In project library / feature modules + implementation(project(":core")) + implementation(project(":database")) + implementation(project(":password_manager")) + implementation(project(":autofill")) + + // Android Core + implementation(libs.appcompat) + implementation(libs.material) + // Jetpack Compose + val composeBom = platform(libs.compose.bom) + implementation(composeBom) implementation(libs.bundles.compose) - implementation(platform(libs.compose.bom)) - implementation(libs.androidx.ui) - implementation(libs.androidx.ui.graphics) - androidTestImplementation(libs.androidx.ui.test.junit4) debugImplementation(libs.bundles.compose.debug) - // Navigation 3 - implementation(libs.bundles.navigation3) - - // Standard Kotlin Libraries - implementation(libs.kotlin.stdlib) - - // UI/Google Services - implementation(libs.material) + // Google Play License Services implementation(libs.oss.license) - implementation(libs.appcompat) - - // Data/Persistence (Room Bundle) - implementation(libs.bundles.room) - debugImplementation(libs.androidx.ui.test.manifest) - ksp(libs.room.compiler) - - // Networking/Parsing - implementation(libs.okhttp) - implementation(libs.json) // Concurrency (Coroutines Bundle) implementation(libs.bundles.coroutines) - // Android Architecture Components (Lifecycle Bundle) - implementation(libs.bundles.lifecycle) - // Dependency Injection - implementation(libs.bundles.koin) + implementation(libs.koin) + implementation(libs.koin.compose) // Datastore Preferences - implementation(libs.bundles.datastore.preferences) - - - // --- Testing --- - - // Local Unit Testing (Unit Test Bundle) - testImplementation(libs.bundles.unit.test) - - // Android Instrumented Testing (Android Test Bundle) - androidTestImplementation(platform(libs.compose.bom)) - androidTestImplementation(libs.bundles.android.test) - androidTestImplementation(libs.room.testing) - androidTestImplementation(libs.bundles.coroutines.test) - androidTestImplementation(libs.truth) // Keeping truth explicit for androidTest, though it's in both bundles. + implementation(libs.androidx.datastore.preferences) } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fc3da90e..a618b668 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,36 +8,26 @@ android:name=".PasscodesApplication" android:allowBackup="true" android:icon="${appIcon}" - android:label="${appLabel}" + android:label="@string/app_name" android:localeConfig="@xml/locales_config" android:requestLegacyExternalStorage="true" - android:roundIcon="@mipmap/ic_launcher_round" + android:roundIcon="${appRoundIcon}" android:supportsRtl="true" android:theme="@style/PasscodesTheme.Default" tools:targetApi="33"> + + android:name=".oldui.MainActivity" + android:exported="true"> - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/utils/Constants.kt b/app/src/main/kotlin/com/jeeldobariya/passcodes/Constants.kt similarity index 73% rename from app/src/main/kotlin/com/jeeldobariya/passcodes/utils/Constants.kt rename to app/src/main/kotlin/com/jeeldobariya/passcodes/Constants.kt index 24a068b5..48fb07b3 100644 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/utils/Constants.kt +++ b/app/src/main/kotlin/com/jeeldobariya/passcodes/Constants.kt @@ -1,4 +1,4 @@ -package com.jeeldobariya.passcodes.utils +package com.jeeldobariya.passcodes object Constant { const val REPOSITORY_SIGNATURE = "PasscodesApp/Passcodes" @@ -14,13 +14,4 @@ object Constant { const val REPORT_BUG_URL = "$REPOSITORY_URL/issues/new?template=bug-report.md" const val RELEASE_NOTE_URL = "$DOCS_REPOSITORY_URL/blob/main/user-docs/release-notes.md" const val SECURITY_GUIDE_URL = "$DOCS_REPOSITORY_URL/blob/main/user-docs/security-guidelines.md" - - - // Shared Preferences Constants - const val APP_PREFS_NAME = "app_prefs" - const val THEME_KEY = "selected_theme" - - const val FEATURE_FLAGS_PREFS_NAME = "feature_flags_prefs" - const val LATEST_FEATURES_KEY = "latest_features_enabled" } - diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/PasscodesApplication.kt b/app/src/main/kotlin/com/jeeldobariya/passcodes/PasscodesApplication.kt index 190dd4f5..fbe29251 100644 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/PasscodesApplication.kt +++ b/app/src/main/kotlin/com/jeeldobariya/passcodes/PasscodesApplication.kt @@ -1,7 +1,9 @@ package com.jeeldobariya.passcodes import android.app.Application -import com.jeeldobariya.passcodes.di.appModule +import com.jeeldobariya.passcodes.core.di.coreModule +import com.jeeldobariya.passcodes.database.di.databaseModule +import com.jeeldobariya.passcodes.password_manager.di.passwordManagerModule import org.koin.android.ext.koin.androidContext import org.koin.core.context.startKoin @@ -10,7 +12,9 @@ class PasscodesApplication : Application() { super.onCreate() startKoin { androidContext(this@PasscodesApplication) - modules(appModule) + modules(coreModule) + modules(passwordManagerModule) + modules(databaseModule) } } } diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/database/MasterDatabase.kt b/app/src/main/kotlin/com/jeeldobariya/passcodes/database/MasterDatabase.kt deleted file mode 100644 index 32515b70..00000000 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/database/MasterDatabase.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.jeeldobariya.passcodes.database - -import android.content.Context -import androidx.room.Database -import androidx.room.Room -import androidx.room.RoomDatabase - -@Database( - entities = [Password::class], - version = 1, - exportSchema = true -) -abstract class MasterDatabase : RoomDatabase() { - abstract val passwordsDao: PasswordsDao - - companion object { - @Volatile - private var INSTANCE: MasterDatabase? = null - - fun getDatabase(context: Context): MasterDatabase { - return INSTANCE ?: synchronized(this) { - - val instance = Room.databaseBuilder( - context.applicationContext, - MasterDatabase::class.java, - "master" - ) - .build() - INSTANCE = instance - instance - } - } - } -} diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/di/appModule.kt b/app/src/main/kotlin/com/jeeldobariya/passcodes/di/appModule.kt deleted file mode 100644 index 65f10a1c..00000000 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/di/appModule.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.jeeldobariya.passcodes.di - -import com.jeeldobariya.passcodes.oldui.LoadPasswordViewModel -import com.jeeldobariya.passcodes.oldui.SavePasswordViewModel -import com.jeeldobariya.passcodes.oldui.UpdatePasswordViewModel -import com.jeeldobariya.passcodes.oldui.ViewPasswordViewModel -import com.jeeldobariya.passcodes.utils.Controller -import org.koin.android.ext.koin.androidContext -import org.koin.core.module.dsl.viewModel -import org.koin.dsl.module - -val appModule = module { - - single { - Controller(androidContext()) - } - - viewModel { - UpdatePasswordViewModel(get()) - } - - viewModel { - SavePasswordViewModel(get()) - } - - viewModel { - LoadPasswordViewModel(get()) - } - - viewModel { - ViewPasswordViewModel(get()) - } - -} diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/AboutUsActivity.kt b/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/AboutUsActivity.kt index 462ec85f..d9752697 100644 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/AboutUsActivity.kt +++ b/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/AboutUsActivity.kt @@ -4,9 +4,9 @@ import android.content.Intent import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.core.net.toUri +import com.jeeldobariya.passcodes.Constant +import com.jeeldobariya.passcodes.core.datastore.appDatastore import com.jeeldobariya.passcodes.databinding.ActivityAboutUsBinding -import com.jeeldobariya.passcodes.utils.Constant -import com.jeeldobariya.passcodes.utils.appDatastore import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/LicenseActivity.kt b/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/LicenseActivity.kt index 042c23d4..ef3cacbe 100644 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/LicenseActivity.kt +++ b/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/LicenseActivity.kt @@ -4,8 +4,8 @@ import android.content.Intent import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.google.android.gms.oss.licenses.OssLicensesMenuActivity +import com.jeeldobariya.passcodes.core.datastore.appDatastore import com.jeeldobariya.passcodes.databinding.ActivityLicenseBinding -import com.jeeldobariya.passcodes.utils.appDatastore import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking import java.io.BufferedReader diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/LoadPasswordAction.kt b/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/LoadPasswordAction.kt deleted file mode 100644 index ff18f46f..00000000 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/LoadPasswordAction.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.jeeldobariya.passcodes.oldui - -sealed interface LoadPasswordAction { - data object RefreshPassword: LoadPasswordAction -} diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/LoadPasswordState.kt b/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/LoadPasswordState.kt deleted file mode 100644 index e017cb43..00000000 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/LoadPasswordState.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.jeeldobariya.passcodes.oldui - -import com.jeeldobariya.passcodes.database.Password - -data class LoadPasswordState( - val passwordEntityList: List = emptyList(), - val isError: Boolean = false -) diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/MainActivity.kt b/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/MainActivity.kt index 881afa13..cf2fae1b 100644 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/MainActivity.kt +++ b/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/MainActivity.kt @@ -6,13 +6,17 @@ import androidx.appcompat.app.AppCompatActivity import androidx.core.view.WindowCompat import androidx.lifecycle.lifecycleScope import com.jeeldobariya.passcodes.BuildConfig +import com.jeeldobariya.passcodes.Constant +import com.jeeldobariya.passcodes.core.datastore.appDatastore +import com.jeeldobariya.passcodes.core.domain.usecases.CheckForUpdateUseCase +import com.jeeldobariya.passcodes.core.feature_flags.featureFlagsDatastore import com.jeeldobariya.passcodes.databinding.ActivityMainBinding -import com.jeeldobariya.passcodes.utils.UpdateChecker -import com.jeeldobariya.passcodes.utils.appDatastore +import com.jeeldobariya.passcodes.password_manager.oldui.PasswordManagerActivity import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking +import org.koin.android.ext.android.inject // import com.jeeldobariya.passcodes.utils.Permissions @@ -22,6 +26,8 @@ class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding + private val checkForUpdateUseCase: CheckForUpdateUseCase by inject() + override fun onCreate(savedInstanceState: Bundle?) { runBlocking { setTheme(appDatastore.data.first().theme) @@ -31,7 +37,11 @@ class MainActivity : AppCompatActivity() { setContentView(binding.root) lifecycleScope.launch(Dispatchers.IO) { - UpdateChecker.checkVersion(this@MainActivity, BuildConfig.VERSION_NAME) + checkForUpdateUseCase( + currentVersion = BuildConfig.VERSION_NAME, + githubReleaseApiUrl = Constant.GITHUB_RELEASE_API_URL, + telegramCommunityUrl = Constant.TELEGRAM_COMMUNITY_URL + ) } // Add event onclick listener @@ -45,6 +55,16 @@ class MainActivity : AppCompatActivity() { permissionsHandle = Permissions(this) if (!permissionsHandle.checkPermission()) permissionsHandle.requestPermission() */ + + runBlocking { + if (featureFlagsDatastore.data.first().isPreviewLayoutEnabled) { + val jetpackComposeActivity = Intent( + this@MainActivity, + com.jeeldobariya.passcodes.ui.MainActivity::class.java + ) + startActivity(jetpackComposeActivity) + } + } } /* Comment the code as permission is not need to write into app data dir. diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/SavePasswordAction.kt b/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/SavePasswordAction.kt deleted file mode 100644 index 14634ce5..00000000 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/SavePasswordAction.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.jeeldobariya.passcodes.oldui - -sealed interface SavePasswordAction { - data class OnChangeDomain(val newDomain: String): SavePasswordAction - data class OnChangeUsername(val newUsername: String): SavePasswordAction - data class OnChangePassword(val newPassword: String): SavePasswordAction - data class OnChangeNotes(val newNotes: String): SavePasswordAction - data object OnSavePasswordButtonClick: SavePasswordAction -} diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/SavePasswordViewModel.kt b/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/SavePasswordViewModel.kt deleted file mode 100644 index 2fce6577..00000000 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/SavePasswordViewModel.kt +++ /dev/null @@ -1,58 +0,0 @@ -package com.jeeldobariya.passcodes.oldui - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.jeeldobariya.passcodes.utils.Controller -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch - -class SavePasswordViewModel( - val controller: Controller -) : ViewModel() { - - private val _state = MutableStateFlow(SavePasswordState()) - val state = _state.asStateFlow() - - fun onAction(action: SavePasswordAction) { - when (action) { - is SavePasswordAction.OnChangeDomain -> { onChangeDomainText(action.newDomain) } - is SavePasswordAction.OnChangeUsername -> { onChangeUsernameText(action.newUsername) } - is SavePasswordAction.OnChangePassword -> { onChangePasswordText(action.newPassword) } - is SavePasswordAction.OnChangeNotes -> { onChangeNotesText(action.newNotes) } - SavePasswordAction.OnSavePasswordButtonClick -> { savePasswordEntity() } - } - } - - private fun onChangeDomainText(newDomain: String) { - _state.update { it.copy(domain = newDomain) } - } - - private fun onChangeUsernameText(newUsername: String) { - _state.update { it.copy(username = newUsername) } - } - - private fun onChangePasswordText(newPassword: String) { - _state.update { it.copy(password = newPassword) } - } - - private fun onChangeNotesText(newNotes: String) { - _state.update { it.copy(notes = newNotes) } - } - - private fun savePasswordEntity() { - viewModelScope.launch { - try { - controller.savePasswordEntity( - _state.value.domain, - _state.value.username, - _state.value.password, - _state.value.notes - ) - } catch (e: Exception) { - _state.update { it.copy(isError = true) } - } - } - } -} diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/SettingsActivity.kt b/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/SettingsActivity.kt index 8ba4be4c..843a8dba 100644 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/SettingsActivity.kt +++ b/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/SettingsActivity.kt @@ -1,5 +1,6 @@ package com.jeeldobariya.passcodes.oldui +import android.content.Intent import android.os.Bundle import android.view.View import android.widget.AdapterView @@ -9,22 +10,27 @@ import androidx.appcompat.app.AppCompatDelegate import androidx.core.os.LocaleListCompat import androidx.core.view.WindowCompat import androidx.lifecycle.lifecycleScope -import com.jeeldobariya.passcodes.R +import com.jeeldobariya.passcodes.autofill.AutofillSettingsActivity +import com.jeeldobariya.passcodes.core.R +import com.jeeldobariya.passcodes.core.datastore.appDatastore +import com.jeeldobariya.passcodes.core.feature_flags.featureFlagsDatastore +import com.jeeldobariya.passcodes.core.utils.collectLatestLifecycleFlow import com.jeeldobariya.passcodes.databinding.ActivitySettingsBinding -import com.jeeldobariya.passcodes.flags.featureFlagsDatastore -import com.jeeldobariya.passcodes.utils.Controller -import com.jeeldobariya.passcodes.utils.appDatastore -import com.jeeldobariya.passcodes.utils.collectLatestLifecycleFlow +import com.jeeldobariya.passcodes.password_manager.data.repository.PasswordRepository import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking +import org.koin.android.ext.android.inject +import kotlin.system.exitProcess class SettingsActivity : AppCompatActivity() { + private val passwordRepository: PasswordRepository by inject() + private lateinit var binding: ActivitySettingsBinding - private lateinit var controller: Controller // List of available themes to cycle through + @Suppress("PrivatePropertyName") private val THEMES = listOf( R.style.PasscodesTheme_Default, R.style.PasscodesTheme_Trusted, @@ -45,9 +51,11 @@ class SettingsActivity : AppCompatActivity() { collectLatestLifecycleFlow(featureFlagsDatastore.data) { binding.switchLatestFeatures.isChecked = it.isPreviewFeaturesEnabled - } + binding.switchLatestLayout.isChecked = it.isPreviewLayoutEnabled - controller = Controller(this) // Initialize the controller here + binding.autofillSettingCard.visibility = + if (it.isPreviewFeaturesEnabled) View.VISIBLE else View.GONE + } // Add event onclick listener addOnClickListenerOnButton() @@ -56,6 +64,7 @@ class SettingsActivity : AppCompatActivity() { WindowCompat.setDecorFitsSystemWindows(window, false) } + // TODO: Shift the language switching logic to viewmodel in core module. private fun setInitialLangSelection() { val currentAppLocales: String = AppCompatDelegate.getApplicationLocales().toLanguageTags() @@ -93,6 +102,8 @@ class SettingsActivity : AppCompatActivity() { binding.toggleThemeBtn.setOnClickListener { lifecycleScope.launch { + // TODO: Shift the theme switching logic to viewmodel in core module. + // INFO: logic here will change with jetpack compose. val currentThemeStyle = appDatastore.data.first().theme val currentIndex = THEMES.indexOf(currentThemeStyle) @@ -101,14 +112,9 @@ class SettingsActivity : AppCompatActivity() { appDatastore.updateData { it.copy(theme = newThemeStyle) } - recreate() + finishAndRemoveTask() + exitProcess(0) } - - Toast.makeText( - this@SettingsActivity, - getString(R.string.restart_app_require), - Toast.LENGTH_SHORT - ).show() } binding.switchLatestFeatures.setOnCheckedChangeListener { _, isChecked -> @@ -117,16 +123,27 @@ class SettingsActivity : AppCompatActivity() { it.copy(isPreviewFeaturesEnabled = isChecked) } } - Toast.makeText( - this@SettingsActivity, - getString(R.string.future_feat_clause) + isChecked.toString(), - Toast.LENGTH_SHORT - ).show() + } + + binding.switchLatestLayout.setOnCheckedChangeListener { _, isChecked -> + lifecycleScope.launch { + featureFlagsDatastore.updateData { + it.copy(isPreviewLayoutEnabled = isChecked) + } + + finishAndRemoveTask() + exitProcess(0) + } + } + + binding.autofillSettingBtn.setOnClickListener { v -> + val autofillSettingsIntent = Intent(this, AutofillSettingsActivity::class.java) + startActivity(autofillSettingsIntent) } binding.clearAllDataBtn.setOnClickListener { v -> lifecycleScope.launch { - controller.clearAllData() + passwordRepository.clearAllData() } Toast.makeText(this@SettingsActivity, "Delete the user data!!", Toast.LENGTH_SHORT) diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/UpdatePasswordAction.kt b/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/UpdatePasswordAction.kt deleted file mode 100644 index 7ef3f60b..00000000 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/UpdatePasswordAction.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.jeeldobariya.passcodes.oldui - -sealed interface UpdatePasswordAction { - data class OnChangeDomain(val newDomain: String): UpdatePasswordAction - data class OnChangeUsername(val newUsername: String): UpdatePasswordAction - data class OnChangePassword(val newPassword: String): UpdatePasswordAction - data class OnChangeNotes(val newNotes: String): UpdatePasswordAction - data object OnUpdatePasswordButtonClick: UpdatePasswordAction -} diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/ViewPasswordAction.kt b/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/ViewPasswordAction.kt deleted file mode 100644 index e40b9a90..00000000 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/oldui/ViewPasswordAction.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.jeeldobariya.passcodes.oldui - -sealed interface ViewPasswordAction { - data class LoadPassword(val passwordId: Int): ViewPasswordAction - data object RefreshPassword: ViewPasswordAction - // data object NavigateUpdatePasswordAction: ViewPasswordAction - data object DeletePasswordAction: ViewPasswordAction -} diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/ui/MainActivity.kt b/app/src/main/kotlin/com/jeeldobariya/passcodes/ui/MainActivity.kt index 07c80f09..b504d923 100644 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/ui/MainActivity.kt +++ b/app/src/main/kotlin/com/jeeldobariya/passcodes/ui/MainActivity.kt @@ -1,6 +1,5 @@ package com.jeeldobariya.passcodes.ui -import android.content.Intent import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent @@ -15,12 +14,16 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.jeeldobariya.passcodes.core.feature_flags.featureFlagsDatastore import com.jeeldobariya.passcodes.ui.ui.theme.PasscodesTheme +import kotlinx.coroutines.launch +import kotlin.system.exitProcess class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -29,8 +32,12 @@ class MainActivity : ComponentActivity() { setContent { PasscodesTheme { MainScreen { - val loginIntent = Intent(this@MainActivity, com.jeeldobariya.passcodes.oldui.MainActivity::class.java) - startActivity(loginIntent) + featureFlagsDatastore.updateData { + it.copy(isPreviewLayoutEnabled = false) + } + + finishAndRemoveTask() + exitProcess(0) } } } @@ -38,7 +45,9 @@ class MainActivity : ComponentActivity() { } @Composable -fun MainScreen(navigateToOldUi: () -> Unit) { +fun MainScreen(navigateToOldUi: suspend () -> Unit) { + val scope = rememberCoroutineScope() + Surface( color = MaterialTheme.colorScheme.surface, modifier = Modifier.fillMaxSize(), @@ -57,19 +66,27 @@ fun MainScreen(navigateToOldUi: () -> Unit) { Spacer(Modifier.padding(12.dp)) Button( - onClick = navigateToOldUi + onClick = { + scope.launch { + navigateToOldUi() + } + } ) { Text("Back To Old UI", fontSize = 20.sp) } Button( - onClick = navigateToOldUi + onClick = { + scope.launch { + navigateToOldUi() + } + } ) { Text("Continue New UI", fontSize = 20.sp) } Spacer(Modifier.padding(12.dp)) - Text("Jetpack UI Is Under Development", fontSize = 6.sp) + Text("Jetpack UI Is Under Development", fontSize = 11.sp) } } } @@ -78,8 +95,8 @@ fun MainScreen(navigateToOldUi: () -> Unit) { @Composable fun GreetingPreview() { PasscodesTheme { - MainScreen { - Unit - } + MainScreen( + navigateToOldUi = { } + ) } } diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/utils/AppSettings.kt b/app/src/main/kotlin/com/jeeldobariya/passcodes/utils/AppSettings.kt deleted file mode 100644 index ec392d03..00000000 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/utils/AppSettings.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.jeeldobariya.passcodes.utils - -// please refer to `app/src/main/kotlin/com/jeeldobariya/passcodes/flags/FeatureFlagsSettings.kt` for Migration Guide. - -import android.content.Context -import androidx.datastore.dataStore -import com.jeeldobariya.passcodes.R -import kotlinx.serialization.Serializable - -val Context.appDatastore by dataStore(fileName = "app-settings.json", serializer = AppSettingsSerializer) - -@Serializable -data class AppSettings( - val theme: Int = R.style.PasscodesTheme_Default, -) diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/utils/Controller.kt b/app/src/main/kotlin/com/jeeldobariya/passcodes/utils/Controller.kt deleted file mode 100644 index edb0ab29..00000000 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/utils/Controller.kt +++ /dev/null @@ -1,225 +0,0 @@ -package com.jeeldobariya.passcodes.utils - -import android.content.Context -import com.jeeldobariya.passcodes.database.MasterDatabase -import com.jeeldobariya.passcodes.database.Password -import com.jeeldobariya.passcodes.database.PasswordsDao -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.first - -class InvalidInputException(message: String = "Input parameters cannot be blank.") : - Exception(message) - -class DatabaseOperationException( - message: String = "A database operation error occurred.", - cause: Throwable? = null -) : Exception(message, cause) - -class PasswordNotFoundException(message: String = "Password with the given ID was not found.") : - Exception(message) - -class InvalidImportFormat(message: String = "Given Data Is In Invalid Format") : Exception(message) - -class Controller(context: Context) { - private val passwordsDao: PasswordsDao - - init { - // Initialize Room database and get the DAO instance - val db = MasterDatabase.getDatabase(context) - passwordsDao = db.passwordsDao - } - - companion object { - const val CSV_HEADER = "name,url,username,password,note" - } - - /** - * Saves a new password entity into the database. - * @return The rowId of the newly inserted row. - * @throws InvalidInputException if parameters are blank. - * @throws DatabaseOperationException if a database error occurs. - */ - suspend fun savePasswordEntity( - domain: String, - username: String, - password: String, - notes: String - ): Long { - if (domain.isBlank() || username.isBlank() || password.isBlank()) { - throw InvalidInputException() - } - - val currentTimestamp = DateTimeUtils.getCurrDateTime() - val newPassword = Password( - domain = domain, - username = username, - password = password, - notes = notes, - createdAt = currentTimestamp, - updatedAt = currentTimestamp - ) - - return try { - passwordsDao.insertPassword(newPassword) - } catch (e: Exception) { - e.printStackTrace() - throw DatabaseOperationException("Error saving password.", e) - } - } - - /** - * Retrieves a password entity by its ID. - * @return The Password object if found. - * @throws DatabaseOperationException if a database error occurs. - * @throws PasswordNotFoundException if the password is not found. - */ - suspend fun getPasswordById(id: Int): Password { - return try { - passwordsDao.getPasswordById(id) - ?: throw PasswordNotFoundException("Password with ID $id not found.") - } catch (e: PasswordNotFoundException) { - throw e - } catch (e: Exception) { - e.printStackTrace() - throw DatabaseOperationException("Error retrieving password by ID.", e) - } - } - - /** - * Retrieves a password entity by username and domain. - * @return The Password object if found. - * @throws DatabaseOperationException if a database error occurs. - */ - suspend fun getPasswordByUsernameAndDomain(username: String, domain: String): Password? { - return try { - passwordsDao.getPasswordByUsernameAndDomain(username, domain) - } catch (e: Exception) { - e.printStackTrace() - throw DatabaseOperationException("Error retrieving password by username and domain.", e) - } - } - - /** - * Retrieves all password entities from the database as a Flow for real-time updates. - * @return A Flow that emits lists of Password objects. - * Room handles the background threading for Flow queries. - */ - fun getAllPasswords(): Flow> { - return passwordsDao.getAllPasswords() - } - - suspend fun updatePassword( - id: Int, - domain: String, - username: String, - password: String, - notes: String - ): Int { - if (domain.isBlank() || username.isBlank() || password.isBlank()) { - throw InvalidInputException() - } - - return try { - val existingPassword = passwordsDao.getPasswordById(id) - ?: throw PasswordNotFoundException("Password with ID $id not found for update.") - - val updatedTimestamp = DateTimeUtils.getCurrDateTime() - val passwordToUpdate = existingPassword.copy( - domain = domain, - username = username, - password = password, - notes = notes, - updatedAt = updatedTimestamp - ) - passwordsDao.updatePassword(passwordToUpdate) - } catch (e: PasswordNotFoundException) { - throw e - } catch (e: Exception) { - e.printStackTrace() - throw DatabaseOperationException("Error updating password.", e) - } - } - - /** - * Deletes a password entity by its ID. - * @return The number of rows deleted (usually 1 if successful, 0 if not found). - * @throws DatabaseOperationException if a database error occurs. - */ - suspend fun deletePassword(id: Int): Int { - return try { - passwordsDao.deletePasswordById(id) - } catch (e: Exception) { - e.printStackTrace() - throw DatabaseOperationException("Error deleting password.", e) - } - } - - suspend fun clearAllData() { - passwordsDao.clearAllPasswordData() - } - - suspend fun exportDataToCsvString(): String { - val passwords: List = getAllPasswords().first() - - val rows = passwords.joinToString("\n") { password -> - "${password.domain},https://local.${password.domain},${password.username},${password.password},${password.notes}" - } - - return CSV_HEADER + "\n" + rows - } - - suspend fun importDataFromCsvString(csvString: String): IntArray { - val lines = csvString.lines().filter { it.isNotBlank() } - - if (lines.isEmpty()) { - throw InvalidImportFormat("Given data seems to be Empty!!") - } - - if (lines[0] != CSV_HEADER) { - throw InvalidImportFormat("Given data is not in valid csv format!! correct format:- ${CSV_HEADER}") - } - - var importedPasswordCount = 0 - var failToImportedPasswordCount = 0 - - lines.drop(1).forEach { line -> - val cols = line.split(",") - - /* NOTE: this need to be done, because our app not allow empty domain. */ - val chosenDomain: String = if (!cols[0].isBlank()) { - cols[0].trim() // used: name - } else cols[1].trim() // used: url - - try { - val password: Password? = passwordsDao.getPasswordByUsernameAndDomain( - username = cols[2].trim(), - domain = chosenDomain - ) - - if (password != null) { - updatePassword( - id = password.id, - domain = password.domain, - username = password.username, - password = cols[3].trim(), - notes = cols[4].trim() - ) - } else { - savePasswordEntity( - domain = chosenDomain, - username = cols[2].trim(), - password = cols[3].trim(), - notes = cols[4].trim() - ) - } - - importedPasswordCount++ - } catch (e: InvalidInputException) { - e.printStackTrace() - failToImportedPasswordCount++ - } - } - - return intArrayOf(importedPasswordCount, failToImportedPasswordCount) - } -} diff --git a/app/src/main/res/drawable-v24/dev_ic_launcher_foreground.xml b/app/src/main/res/drawable/dev_ic_launcher_foreground.xml similarity index 100% rename from app/src/main/res/drawable-v24/dev_ic_launcher_foreground.xml rename to app/src/main/res/drawable/dev_ic_launcher_foreground.xml diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml index 07d5da9c..4e75da69 100644 --- a/app/src/main/res/drawable/ic_launcher_background.xml +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -1,9 +1,11 @@ + android:viewportHeight="108" + tools:keep="@drawable/ic_launcher_background"> diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml similarity index 92% rename from app/src/main/res/drawable-v24/ic_launcher_foreground.xml rename to app/src/main/res/drawable/ic_launcher_foreground.xml index 2b068d11..95452525 100644 --- a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -1,9 +1,11 @@ + android:viewportHeight="108" + tools:keep="@drawable/ic_launcher_foreground"> + android:textColor="?attr/colorOnSurfaceVariant" /> + android:textColor="?attr/colorOnSurface" /> + android:useDefaultMargins="true" + tools:ignore="UseCompoundDrawables"> + android:padding="16dp"> + + app:tint="?attr/colorPrimary" /> + + android:textAlignment="center" + android:textAppearance="@style/TextAppearance.Material3.LabelLarge" /> @@ -101,22 +102,24 @@ + android:padding="16dp"> + + app:tint="?attr/colorPrimary" /> + + android:textAlignment="center" + android:textAppearance="@style/TextAppearance.Material3.LabelLarge" /> @@ -132,22 +135,24 @@ + android:padding="16dp"> + + app:tint="?attr/colorPrimary" /> + + android:textAlignment="center" + android:textAppearance="@style/TextAppearance.Material3.LabelLarge" /> @@ -163,41 +168,44 @@ + android:padding="16dp"> + + app:tint="?attr/colorPrimary" /> + + android:textAlignment="center" + android:textAppearance="@style/TextAppearance.Material3.LabelLarge" /> + + app:cardBackgroundColor="?attr/colorSecondaryContainer" + app:cardCornerRadius="16dp"> + android:padding="16dp"> + + android:textAlignment="center" + android:textAppearance="@style/TextAppearance.Material3.LabelLarge" /> @@ -223,31 +232,54 @@ android:layout_marginTop="24dp" android:layout_marginBottom="16dp" android:text="@string/label_contributor" - android:textColor="?attr/colorOnSurface"/> + android:textColor="?attr/colorOnSurface" /> + android:layout_marginBottom="8dp" + android:backgroundTint="?attr/colorTertiaryContainer" + app:cardCornerRadius="16dp"> + + android:textColor="?attr/colorTertiary" + android:text="@string/developer_name" + android:textAppearance="@style/TextAppearance.Material3.BodyLarge" /> + + + + + + + android:textColor="?attr/colorTertiary" + android:text="@string/co_developer" + android:textAppearance="@style/TextAppearance.Material3.BodyLarge" /> diff --git a/app/src/main/res/layout/activity_license.xml b/app/src/main/res/layout/activity_license.xml index f0fd632b..3413f7c4 100644 --- a/app/src/main/res/layout/activity_license.xml +++ b/app/src/main/res/layout/activity_license.xml @@ -1,11 +1,9 @@ - @@ -17,8 +15,8 @@ + android:gravity="center" + android:orientation="vertical"> - - - - - - - diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 19b40a2c..f7b5cd6d 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -4,21 +4,21 @@ android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" - tools:context=".oldui.MainActivity" - android:padding="4sp" > + android:padding="4sp" + tools:context=".oldui.MainActivity"> + android:orientation="vertical"> + android:orientation="vertical"> - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/activity_save_password.xml b/app/src/main/res/layout/activity_save_password.xml deleted file mode 100644 index b092f4ad..00000000 --- a/app/src/main/res/layout/activity_save_password.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 05eb2d2f..939a0671 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -1,6 +1,5 @@ - + android:textSize="32sp" /> + android:textSize="16sp" /> + android:layout_gravity="right|center_vertical" + android:entries="@array/lang_options" /> @@ -64,26 +63,26 @@ + android:textSize="16sp" /> + android:textSize="12sp" /> @@ -98,29 +97,60 @@ + android:layout_margin="8dp" + android:text="@string/latest_feature" + android:textColor="?attr/colorPrimary" + android:textSize="16sp" /> + android:layout_margin="8dp" + tools:ignore="UseSwitchCompatOrMaterialXml" /> + + + + + + + + + + + + + + + + + + + android:textSize="12sp" /> diff --git a/app/src/main/res/layout/activity_update_password.xml b/app/src/main/res/layout/activity_update_password.xml deleted file mode 100644 index 3713d5dc..00000000 --- a/app/src/main/res/layout/activity_update_password.xml +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/activity_view_password.xml b/app/src/main/res/layout/activity_view_password.xml deleted file mode 100644 index e5664129..00000000 --- a/app/src/main/res/layout/activity_view_password.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 345888d2..00000000 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 345888d2..00000000 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/dev_ic_launcher.xml b/app/src/main/res/mipmap-anydpi/dev_ic_launcher.xml similarity index 100% rename from app/src/main/res/mipmap-anydpi-v26/dev_ic_launcher.xml rename to app/src/main/res/mipmap-anydpi/dev_ic_launcher.xml diff --git a/app/src/main/res/mipmap-anydpi-v26/dev_ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi/dev_ic_launcher_round.xml similarity index 100% rename from app/src/main/res/mipmap-anydpi-v26/dev_ic_launcher_round.xml rename to app/src/main/res/mipmap-anydpi/dev_ic_launcher_round.xml diff --git a/app/src/main/res/mipmap-anydpi/ic_launcher.xml b/app/src/main/res/mipmap-anydpi/ic_launcher.xml new file mode 100644 index 00000000..a83cd238 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml new file mode 100644 index 00000000..a83cd238 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 77dd7c90..43624228 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -4,33 +4,15 @@ Entwickelt von: Jeel Dobariya - UI/UX Design von: Hamada Issas (Native) Codepflege & Tests: Achmad Daniel (Kudanill) - Beenden - Ein Open-Source-Passwort-Manager, der dir hilft, Passwörter nicht mehr selbst merken zu müssen. Diese App befindet sich noch in der Entwicklung und ist nur für Lern- und Testzwecke gedacht. Sie ist möglicherweise nicht sicher für sensible Daten. Bitte lies die Sicherheitshinweise. - Domain - Name der zugehörigen Webseite oder Domain - Benutzername - Passwort - Notizen - z. B. Google, Instagram, WhatsApp usw. - z. B. Liam15, Noha, Olivia, Ava_25 usw. - z. B. 12345, abc123xyz, qwerty usw. Passwort-Manager - Speichern - Laden - Aktualisieren - Löschen - Importieren - Exportieren - Sicherheitsprüfung Einstellungen Design wechseln Sprache: @@ -43,45 +25,17 @@ Änderungsprotokoll - Passwort-Manager - Passwort laden - Passwort speichern - Passwort anzeigen - Passwort aktualisieren Einstellungen Über uns - ID: - Domain: - Benutzername: - Passwort: - Notizen: - Erstellt am: - Aktualisiert am: - Zugriff erlaubt - Zugriff verweigert - App muss neu gestartet werden. - Diese Funktion ist in Arbeit. - 404: Nicht gefunden - Bitte zuerst das Formular ausfüllen. - Fehler: Bitte versuche es erneut. - Erfolg: - Erfolgreich aktualisiert - Erfolgreich gelöscht Etwas ist schiefgelaufen - Aktion abgebrochen Fehler: Ungültige ID!! - Passwort aktualisieren? - Passwort löschen? - Dieser Vorgang kann nicht rückgängig gemacht werden. - Bestätigen - Abbrechen diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index f9dc64eb..c10709c0 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -3,33 +3,15 @@ Desarrollado por: Dobariya Jeel - Diseño UI/UX por: Hamada Issas (Native) Mantenimiento de código y pruebas: Achmad Daniel (Kudanill) - Salir - Un gestor de contraseñas de código abierto que te ayuda a no tener que recordar tus contraseñas. Esta app está en desarrollo activo y es solo para fines educativos y experimentales. Puede que no sea segura para guardar información sensible. Consulta las directrices de seguridad para más detalles. - Dominio - Nombre del sitio web o dominio - Usuario - Contraseña - Notas - Ej: Google, Instagram, WhatsApp, etc. - Ej: Liam15, Noha, Olivia, Ava_25, etc. - Ej: 12345, abc123xyz, qwerty, etc. Gestor de Contraseñas - Guardar Contraseña - Cargar Contraseña - Actualizar Contraseña - Eliminar Contraseña - Importar Contraseña - Exportar Contraseña - Revisar Seguridad Ajustes Cambiar Tema Idioma: @@ -42,44 +24,16 @@ Ver Cambios - Gestor de Contraseñas - Cargar Contraseña - Guardar Contraseña - Ver Contraseña - Actualizar Contraseña Ajustes Sobre Nosotros - ID: - Dominio: - Usuario: - Contraseña: - Notas: - Creado el: - Actualizado el: - Permiso concedido - Permiso denegado - Es necesario reiniciar la app. - Esta función está en desarrollo. - 404: No encontrado. - Aviso: Por favor, completa el formulario primero. - Falló: Intenta de nuevo. - Éxito: - Actualizado correctamente. - Eliminado correctamente. Algo salió mal. - Acción descartada. Algo salió mal: ¡ID inválido! - ¿Actualizar contraseña? - ¿Eliminar contraseña? - Esta acción no se puede deshacer. - Confirmar - Cancelar diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 919aadc8..025b6822 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -4,33 +4,15 @@ डेवलप किया गया: जीत डोबरिया - यूआई/यूएक्स डिजाइन: हामदा इस्सास (नेटिव) कोड मेंटेनेंस और टेस्टिंग: अहमद डेनियल (कुडानिल) - बंद करें - ओपन-सोर्स पासवर्ड मैनेजर जो पासवर्ड याद रखने की झंझट को खत्म करता है। यह ऐप अभी डेवलपमेंट में है और सिर्फ एजुकेशनल और एक्सपेरिमेंटल यूज़ के लिए है। जरूरी डेटा स्टोर करने के लिए यह सिक्योर नहीं हो सकता। कृपया सिक्योरिटी गाइडलाइंस देखें। - डोमेन - वेबसाइट या डोमेन का नाम - यूज़रनेम - पासवर्ड - नोट्स - जैसे Google, Instagram, WhatsApp वगैरह - जैसे Liam15, Noha, Olivia, Ava_25 वगैरह - जैसे 12345, abc123xyz, qwerty वगैरह पासवर्ड मैनेजर - पासवर्ड सेव करें - पासवर्ड लोड करें - पासवर्ड अपडेट करें - पासवर्ड हटाएं - पासवर्ड इंपोर्ट करें - पासवर्ड एक्सपोर्ट करें - सिक्योरिटी चेक सेटिंग्स थीम बदलें भाषा: @@ -43,45 +25,17 @@ चेंजलॉग देखें - पासवर्ड मैनेजर - पासवर्ड लोड करें - पासवर्ड सेव करें - पासवर्ड देखें - पासवर्ड अपडेट करें सेटिंग्स हमारे बारे में - आईडी: - डोमेन: - यूज़रनेम: - पासवर्ड: - नोट्स: - बनाया गया: - अपडेट किया गया: - परमिशन मिल गई - परमिशन नहीं मिली - ऐप को फिर से शुरू करना जरूरी है। - यह फीचर अभी बन रहा है। - 404: नहीं मिला। - चेतावनी: पहले फॉर्म भरें। - फेल हुआ: फिर से कोशिश करें। - सफलता: - सफलतापूर्वक अपडेट हुआ। - सफलतापूर्वक हटाया गया। कुछ गलत हो गया। - कार्रवाई रद्द की गई। कुछ गलत हुआ: ID सही नहीं है!! - पासवर्ड अपडेट करें? - पासवर्ड हटाएं? - यह काम वापस नहीं लिया जा सकता। - पक्का करें - रद्द करें diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 5bae11d9..ae217642 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -4,33 +4,15 @@ Dikembangkan oleh: Jeel Dobariya - Desain UI/UX oleh: Hamada Issas (Native) - Tester: Achmad Daniel (Kudanill) + Pemelihara kode & Tester: Achmad Daniel (Kudanill) - Keluar - Pengelola kata sandi open-source yang bantu kamu bebas dari repotnya mengingat password. Aplikasi ini masih dalam tahap pengembangan aktif dan ditujukan untuk pembelajaran dan eksperimen. Mungkin belum aman untuk menyimpan informasi penting. Silakan baca panduan keamanan untuk info lebih lanjut. - Domain - Nama situs web atau domain yang digunakan - Nama pengguna - Kata sandi - Catatan - cth. Google, Instagram, WhatsApp, dll. - cth. Liam15, Noha, Olivia, Ava_25, dll. - cth. 12345, abc123xyz, qwerty, dll. Pengelola Kata Sandi - Simpan Kata Sandi - Muat Kata Sandi - Perbarui Kata Sandi - Hapus Kata Sandi - Impor Kata Sandi - Ekspor Kata Sandi - Cek Keamanan Pengaturan Ganti Tema Bahasa: @@ -43,45 +25,17 @@ Lihat Changelog - Pengelola Kata Sandi - Muat Kata Sandi - Simpan Kata Sandi - Lihat Kata Sandi - Perbarui Kata Sandi Pengaturan Tentang Kami - ID: - Domain: - Nama Pengguna: - Kata Sandi: - Catatan: - Dibuat: - Diperbarui: - Izin diberikan - Izin ditolak - Aplikasi perlu dimulai ulang. - Fitur ini sedang dikembangkan. - 404: Tidak ditemukan. - Peringatan: Harap isi formulir dulu. - Gagal: Coba lagi nanti. - Berhasil: - Berhasil diperbarui. - Berhasil dihapus. Terjadi kesalahan. - Aksi dibatalkan. Terjadi kesalahan: ID tidak valid!! - Perbarui kata sandi? - Hapus kata sandi? - Tindakan ini tidak dapat dibatalkan. - Konfirmasi - Batal diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index c4644abe..b7d45dff 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -4,33 +4,15 @@ 開発者:Jeel Dobariya - UI/UXデザイン:Hamada Issas(Native) コード管理・テスト:Achmad Daniel(Kudanill) - 終了 - パスワードを覚える手間をなくす、オープンソースのパスワードマネージャーです。 このアプリは開発中で、教育・実験目的のみでの使用を想定しています。機密情報の保存には安全でない可能性があります。セキュリティガイドラインをご確認ください。 - ドメイン - 関連するウェブサイトやドメインの名前 - ユーザー名 - パスワード - メモ - 例:Google、Instagram、WhatsApp など - 例:Liam15、Noha、Olivia、Ava_25 など - 例:12345、abc123xyz、qwerty など パスワードマネージャー - 保存 - 読み込み - 更新 - 削除 - インポート - エクスポート - セキュリティチェック 設定 テーマ切替 言語: @@ -43,45 +25,17 @@ 更新履歴 - パスワードマネージャー - パスワード読み込み - パスワード保存 - パスワードを見る - パスワード更新 設定 アプリについて - ID: - ドメイン: - ユーザー名: - パスワード: - メモ: - 作成日: - 更新日: - 許可されました - 許可されませんでした - アプリを再起動する必要があります。 - この機能は現在開発中です。 - 404:見つかりませんでした - 警告:フォームを入力してください - 失敗しました:もう一度お試しください - 成功: - 更新に成功しました - 削除に成功しました 問題が発生しました - 操作がキャンセルされました エラー:無効なIDです!! - パスワードを更新しますか? - パスワードを削除しますか? - この操作は元に戻せません。 - 確認 - キャンセル diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index e0932b44..9514f8d1 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -4,33 +4,15 @@ 개발자: Jeel Dobariya - UI/UX 디자인: Hamada Issas (Native) 코드 유지보수 및 테스트: Achmad Daniel (Kudanill) - 종료 - 비밀번호 기억하기 귀찮을 때 사용하는 오픈소스 비밀번호 관리자입니다. 이 앱은 현재 개발 중이며 교육 및 실험용으로만 사용해야 합니다. 중요한 정보를 저장하기엔 아직 안전하지 않을 수 있습니다. 보안 가이드를 꼭 참고해주세요. - 도메인 - 사이트 또는 도메인 이름 - 사용자 이름 - 비밀번호 - 메모 - 예: Google, Instagram, WhatsApp 등 - 예: Liam15, Noha, Olivia, Ava_25 등 - 예: 12345, abc123xyz, qwerty 등 비밀번호 관리자 - 비밀번호 저장 - 비밀번호 불러오기 - 비밀번호 수정 - 비밀번호 삭제 - 비밀번호 가져오기 - 비밀번호 내보내기 - 보안 확인 설정 테마 전환 언어: @@ -43,45 +25,17 @@ 변경 기록 - 비밀번호 관리자 - 비밀번호 불러오기 - 비밀번호 저장 - 비밀번호 보기 - 비밀번호 수정 설정 앱 정보 - ID: - 도메인: - 사용자 이름: - 비밀번호: - 메모: - 생성일: - 수정일: - 권한 허용됨 - 권한 거부됨 - 앱을 다시 시작해야 해요. - 이 기능은 아직 개발 중입니다. - 404: 찾을 수 없음 - 주의: 먼저 양식을 작성해주세요. - 실패: 다시 시도해주세요. - 성공: - 성공적으로 수정되었습니다. - 성공적으로 삭제되었습니다. 문제가 발생했습니다. - 작업이 취소되었습니다. 문제 발생: 잘못된 ID입니다!! - 비밀번호를 수정할까요? - 비밀번호를 삭제할까요? - 이 작업은 되돌릴 수 없습니다. - 확인 - 취소 diff --git a/app/src/main/res/values-kr/strings.xml b/app/src/main/res/values-kr/strings.xml index 60d12bb7..944c344c 100644 --- a/app/src/main/res/values-kr/strings.xml +++ b/app/src/main/res/values-kr/strings.xml @@ -3,33 +3,15 @@ Jaejak: Dobariya Jeel - UI/UX Design: Hamada Issas (Native) Code Maintenance & Test: Achmad Daniel (Kudanill) - Jeolryo - Gieokhagi himdeun byeol-ui bimilbeonho jeongnihae juseyo. I app-eun open-source-imnida! I app-eun jigeum gaebal jung-imnida. hakseup mit silheom mokjeok-euro ssie juseyo. hwaldongjeog-in seculi anjeon-eun bojangdoeji anhassseubnida. - Domain - Website name ttoneun domain - I-yongja - Bimilbeonho - Bijul - 예: Google, Instagram, WhatsApp - 예: Liam15, Noha, Ava_25 - 예: 12345, abc123xyz Bimilbeonho Gwanli - Jeojang - Buteowagi - Gengsin - Sakje - Import - Export - Anjeon Seolmyeong Seoljeong Tema Byeongyeong Eon-eo: @@ -42,44 +24,16 @@ Byeon-gye Nolog Bogi - Bimilbeonho Gwanli - Bimilbeonho Buteowagi - Bimilbeonho Jeojang - Bimilbeonho Bogi - Bimilbeonho Gengsin Seoljeong Ulineun Nuguinga - ID: - Domain: - I-yongja: - Bimilbeonho: - Bijul: - Sangseong ilja: - Gengsin ilja: - Heung-in doem - Geohwa doem - Aeb-eul dasi sijakhaeya haeyo. - I gineung-eun majimag junbi jung-imnida. - 404: Chal su eobs-eum - Gyeong-go: Munsuhyeong-eul da chaeujuseyo. - Silpae: Dasi sihae juseyo. - Seong-gong: - Seong-gongjeog-eulo gengsin! - Jeong sangjeongdoe-eossseubnida. Mueonga jalmosdoeeossseubnida. - Haengdong jeohwa Jalmosdoe-eossseubnida: ID Mubeon! - Gengsin haneun geos-eulo hal-kka? - Jeongmal sangjehal-kka? - I haengdong-eun dora gal su eobs-seubnida. - Hwagin - Jeohwa diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 7f9ba695..6c46536a 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -4,33 +4,15 @@ Phát triển bởi: Jeel Dobariya - Thiết kế UI/UX: Hamada Issas (Native) Bảo trì & Kiểm thử mã: Achmad Daniel (Kudanill) - Thoát - Trình quản lý mật khẩu mã nguồn mở giúp bạn không cần nhớ mật khẩu nữa. Ứng dụng này đang được phát triển và chỉ dùng cho mục đích học tập hoặc thử nghiệm. Có thể chưa đủ an toàn để lưu thông tin nhạy cảm. Vui lòng xem hướng dẫn bảo mật để biết thêm chi tiết. - Tên miền - Tên trang web hoặc tên miền liên quan - Tên người dùng - Mật khẩu - Ghi chú - vd: Google, Instagram, WhatsApp, v.v. - vd: Liam15, Noha, Olivia, Ava_25, v.v. - vd: 12345, abc123xyz, qwerty, v.v. Quản lý Mật khẩu - Lưu mật khẩu - Tải mật khẩu - Cập nhật mật khẩu - Xóa mật khẩu - Nhập mật khẩu - Xuất mật khẩu - Kiểm tra bảo mật Cài đặt Chuyển giao diện Ngôn ngữ: @@ -43,45 +25,17 @@ Xem lịch sử thay đổi - Quản lý Mật khẩu - Tải Mật khẩu - Lưu Mật khẩu - Xem Mật khẩu - Cập nhật Mật khẩu Cài đặt Giới thiệu - ID: - Tên miền: - Tên người dùng: - Mật khẩu: - Ghi chú: - Tạo lúc: - Cập nhật lúc: - Đã cấp quyền - Từ chối quyền - Cần khởi động lại ứng dụng. - Tính năng đang được phát triển. - 404: Không tìm thấy - Vui lòng điền vào biểu mẫu trước. - Thất bại: Vui lòng thử lại. - Thành công: - Cập nhật thành công. - Xóa thành công. Đã xảy ra lỗi. - Đã hủy hành động. Lỗi: ID không hợp lệ!! - Cập nhật mật khẩu? - Xóa mật khẩu? - Hành động này không thể hoàn tác. - Xác nhận - Hủy diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 7cc92a7e..61f069c3 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -4,33 +4,15 @@ 开发者:Jeel Dobariya - UI/UX 设计:Hamada Issas(Native) 代码维护与测试:Achmad Daniel(Kudanill) - 退出 - 一个开源的密码管理器,帮你省去记密码的烦恼。 该应用正在积极开发中,仅用于学习和实验目的。暂不建议用于存储敏感信息。请查看安全指南了解详情。 - 域名 - 对应的网站或域名 - 用户名 - 密码 - 备注 - 例如:Google、Instagram、WhatsApp 等 - 例如:Liam15、Noha、Olivia、Ava_25 等 - 例如:12345、abc123xyz、qwerty 等 密码管理器 - 保存密码 - 加载密码 - 更新密码 - 删除密码 - 导入密码 - 导出密码 - 安全检查 设置 切换主题 语言: @@ -43,45 +25,17 @@ 查看更新记录 - 密码管理器 - 加载密码 - 保存密码 - 查看密码 - 更新密码 设置 关于我们 - ID: - 域名: - 用户名: - 密码: - 备注: - 创建时间: - 更新时间: - 已授予权限 - 权限被拒绝 - 需要重新启动应用。 - 该功能正在开发中。 - 404:未找到 - 请先填写表单。 - 失败:请重试。 - 成功: - 更新成功。 - 删除成功。 发生错误。 - 操作已取消。 错误:无效的 ID!! - 要更新密码吗? - 要删除密码吗? - 此操作无法撤销。 - 确认 - 取消 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fd9d9e28..eae9d483 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,46 +1,28 @@ - Passcodes - v1.1.2-rc2 + Passcodes Latest + v0.0.0 - Latest - Developed by: Dobariya Jeel - UI/UX Design by: Hamada Issas (Native) - Code Maintenance & Testing: Achmad Daniel (Kudanill) - - - Quit + Developed by: Dobariya Jeel (@JeelDobariya38) + Code Maintenance & Testing: Achmad Daniel (@kudanilll) + Co-Developer: Hex-Code (@hexCode63) An open-source password manager that helps eliminate the headache of remembering your passwords. This app is currently under active development and is intended for educational and experimental purposes. It may not be secure for storing sensitive authentication information. Please review the security guidelines for more details. - Domain - The name of the website or domain associated - Username - Password - Notes - Copied Successfully - e.g. Google, Instagram, WhatsApp, etc. - e.g. Liam15, Noha, Olivia, Ava_25, etc. - e.g. 12345, abc123xyz, qwerty, etc. Password Manager - Copy Password - Save Password - Load Password - Update Password - Delete Password - Import G-Password - Export G-Password Clear Data - Check Security Settings Toggle Theme Language: Contributor: Themes: Preview Features: + Preview Layout: + Autofill Settings About Us @@ -52,51 +34,14 @@ Passcodes Telegram Community - Password Manager - Load Password - Save Password - View Password - Update Password Settings About Us - - ID: - Domain: - Username: - Password: - Notes: - Created At: - Last Updated: - - - Permission granted - Permission denied - - Restart App Require. - This feature is currently under development. - This is preview feature.. Might have Bugs... - 404: Not found. - Warning: Please fill out the form first. - Failed: Please try again. - Success: - Updated successfully. - Deleted successfully. + This is preview feature… Might have Bugs… Something went wrong. - Action discarded. Something Went Wrong: Invalid ID!! - Imported %1$d passwords - Failed to import %1$d passwords - Passwords exported - Copy to Clipboard? - Update password? - Delete password? - This action cannot be undone. - Copying sensitive data like passwords to clipboard is not so good for security!!! - Confirm - Discard Passcodes Logo diff --git a/app/src/main/res/xml/locales_config.xml b/app/src/main/res/xml/locales_config.xml index 6f5fa173..e1e59369 100644 --- a/app/src/main/res/xml/locales_config.xml +++ b/app/src/main/res/xml/locales_config.xml @@ -1,12 +1,12 @@ - - - - - - - - - + + + + + + + + + diff --git a/autofill/.gitignore b/autofill/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/autofill/.gitignore @@ -0,0 +1 @@ +/build diff --git a/autofill/build.gradle.kts b/autofill/build.gradle.kts new file mode 100644 index 00000000..a6e9909f --- /dev/null +++ b/autofill/build.gradle.kts @@ -0,0 +1,59 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.ksp) +} + +kotlin { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_21) + } +} + +android { + namespace = "com.jeeldobariya.passcodes.autofill" + compileSdk { + version = release(36) + } + + defaultConfig { + minSdk = 26 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + getByName("release") { + isMinifyEnabled = false + } + + create("staging") { + isMinifyEnabled = false + } + + getByName("debug") { + isShrinkResources = false + isMinifyEnabled = false + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + } +} + +dependencies { + // implementation(project(":password_manager")) + + implementation(libs.androidx.core.ktx) + implementation(libs.appcompat) + implementation(libs.material) + + // Data/Persistence (Room Bundle) + ksp(libs.room.compiler) + implementation(libs.room.ktx) +} diff --git a/autofill/consumer-rules.pro b/autofill/consumer-rules.pro new file mode 100644 index 00000000..e69de29b diff --git a/autofill/proguard-rules.pro b/autofill/proguard-rules.pro new file mode 100644 index 00000000..f1b42451 --- /dev/null +++ b/autofill/proguard-rules.pro @@ -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 diff --git a/autofill/src/main/AndroidManifest.xml b/autofill/src/main/AndroidManifest.xml new file mode 100644 index 00000000..6b530eaf --- /dev/null +++ b/autofill/src/main/AndroidManifest.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/autofill/AutofillSettingsActivity.kt b/autofill/src/main/kotlin/com/jeeldobariya/passcodes/autofill/AutofillSettingsActivity.kt similarity index 87% rename from app/src/main/kotlin/com/jeeldobariya/passcodes/autofill/AutofillSettingsActivity.kt rename to autofill/src/main/kotlin/com/jeeldobariya/passcodes/autofill/AutofillSettingsActivity.kt index 3319e917..9fd66f0c 100644 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/autofill/AutofillSettingsActivity.kt +++ b/autofill/src/main/kotlin/com/jeeldobariya/passcodes/autofill/AutofillSettingsActivity.kt @@ -4,8 +4,8 @@ import android.content.Intent import android.os.Bundle import android.provider.Settings import androidx.appcompat.app.AppCompatActivity +import androidx.core.net.toUri import com.google.android.material.button.MaterialButton -import com.jeeldobariya.passcodes.R class AutofillSettingsActivity : AppCompatActivity() { @@ -16,7 +16,7 @@ class AutofillSettingsActivity : AppCompatActivity() { val enableAutofillButton = findViewById(R.id.enable_autofill_button) enableAutofillButton.setOnClickListener { val intent = Intent(Settings.ACTION_REQUEST_SET_AUTOFILL_SERVICE) - intent.data = android.net.Uri.parse("package:$packageName") + intent.data = "package:$packageName".toUri() startActivity(intent) } } diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/autofill/PasswordAutofillService.kt b/autofill/src/main/kotlin/com/jeeldobariya/passcodes/autofill/PasswordAutofillService.kt similarity index 94% rename from app/src/main/kotlin/com/jeeldobariya/passcodes/autofill/PasswordAutofillService.kt rename to autofill/src/main/kotlin/com/jeeldobariya/passcodes/autofill/PasswordAutofillService.kt index 0f3c8787..c460aa12 100644 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/autofill/PasswordAutofillService.kt +++ b/autofill/src/main/kotlin/com/jeeldobariya/passcodes/autofill/PasswordAutofillService.kt @@ -10,7 +10,6 @@ import android.service.autofill.SaveCallback import android.service.autofill.SaveRequest import android.view.autofill.AutofillValue import android.widget.RemoteViews -import com.jeeldobariya.passcodes.R import com.jeeldobariya.passcodes.autofill.data.Passcode import com.jeeldobariya.passcodes.autofill.data.PasscodeDatabase import kotlinx.coroutines.CoroutineScope @@ -18,6 +17,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch +// TODO: currently the code here serves as a foundation for autofill features.. class PasswordAutofillService : AutofillService() { private val serviceScope = CoroutineScope(Dispatchers.IO) @@ -49,6 +49,7 @@ class PasswordAutofillService : AutofillService() { } serviceScope.launch { + // TODO: use the database module instead of separate database val passcodes = PasscodeDatabase.getDatabase(applicationContext).passcodeDao().getAllPasscodes() .first() @@ -91,7 +92,7 @@ class PasswordAutofillService : AutofillService() { } callback.onSuccess() } else { - callback.onFailure("Could not save credentials.") + callback.onFailure(getString(R.string.could_not_save_credentials)) } } diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/autofill/data/Passcode.kt b/autofill/src/main/kotlin/com/jeeldobariya/passcodes/autofill/data/Passcode.kt similarity index 100% rename from app/src/main/kotlin/com/jeeldobariya/passcodes/autofill/data/Passcode.kt rename to autofill/src/main/kotlin/com/jeeldobariya/passcodes/autofill/data/Passcode.kt diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/autofill/data/PasscodeDao.kt b/autofill/src/main/kotlin/com/jeeldobariya/passcodes/autofill/data/PasscodeDao.kt similarity index 100% rename from app/src/main/kotlin/com/jeeldobariya/passcodes/autofill/data/PasscodeDao.kt rename to autofill/src/main/kotlin/com/jeeldobariya/passcodes/autofill/data/PasscodeDao.kt diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/autofill/data/PasscodeDatabase.kt b/autofill/src/main/kotlin/com/jeeldobariya/passcodes/autofill/data/PasscodeDatabase.kt similarity index 100% rename from app/src/main/kotlin/com/jeeldobariya/passcodes/autofill/data/PasscodeDatabase.kt rename to autofill/src/main/kotlin/com/jeeldobariya/passcodes/autofill/data/PasscodeDatabase.kt diff --git a/app/src/main/res/layout/activity_autofill_settings.xml b/autofill/src/main/res/layout/activity_autofill_settings.xml similarity index 64% rename from app/src/main/res/layout/activity_autofill_settings.xml rename to autofill/src/main/res/layout/activity_autofill_settings.xml index 1e1fb8db..73230313 100644 --- a/app/src/main/res/layout/activity_autofill_settings.xml +++ b/autofill/src/main/res/layout/activity_autofill_settings.xml @@ -9,21 +9,29 @@ + + + android:text="@string/open_settings" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/autofill_list_item.xml b/autofill/src/main/res/layout/autofill_list_item.xml similarity index 100% rename from app/src/main/res/layout/autofill_list_item.xml rename to autofill/src/main/res/layout/autofill_list_item.xml diff --git a/autofill/src/main/res/values/strings.xml b/autofill/src/main/res/values/strings.xml new file mode 100644 index 00000000..dae15923 --- /dev/null +++ b/autofill/src/main/res/values/strings.xml @@ -0,0 +1,8 @@ + + + Enable Passcodes Autofill + To use Passcodes as your password manager, you need to enable it as an autofill service in your device settings. + Open Settings + Passcodes Autofill is preview feature and shouldn\'t be use in production!! + Could not save credentials. + diff --git a/app/src/main/res/xml/autofill_service.xml b/autofill/src/main/res/xml/autofill_service.xml similarity index 54% rename from app/src/main/res/xml/autofill_service.xml rename to autofill/src/main/res/xml/autofill_service.xml index eb9e48c4..54a9b6dc 100644 --- a/app/src/main/res/xml/autofill_service.xml +++ b/autofill/src/main/res/xml/autofill_service.xml @@ -1,4 +1,3 @@ - diff --git a/build.gradle.kts b/build.gradle.kts index 0dc3239c..38f2a5a7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,6 +5,7 @@ plugins { alias(libs.plugins.jetbrains.kotlin.serialization) apply false alias(libs.plugins.ksp) apply false alias(libs.plugins.oss.licenses) apply false + alias(libs.plugins.android.library) apply false } // All projects block is common for setting up common repositories for all subprojects. diff --git a/changelog.md b/changelog.md index 113a31eb..c102cd9c 100644 --- a/changelog.md +++ b/changelog.md @@ -4,20 +4,71 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -Release Notes: [docs/release-notes.md](docs/release-notes.md), there you will find short and sweet release notes. +We don't strictly follow them. but the exceptions are very less, very intuitive, obvious +and well documented in our release workflow docs. > [!NOTE] > This is a raw version of the file.. -> -> Final version is over on [PasscodesApp/Passcodes-Docs](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/user-docs/changelog.md) +> +> Final version can be found over +> +at [PasscodesApp/Passcodes-Docs](https://github.com/PasscodesApp/Passcodes-Docs/blob/main/user-docs/changelog.md) + +## v1.1.2 - Alpha (Nov 15, 2025) + +
+ View Internal Details + + ``` + Pacakage Name = "com.jeeldobariya.passcodes" + Min Android = 8.0 (API level 26) + Max Android = 14 (API level 34) + Version Code = 3 + Version Name = "v1.1.2-Alpha" + Master Database Version = "v1" + ``` + +
+ +### Breaking Changes + +- **Migrate to DataStore**: changed the way how setting and feature flag were been storage + previously, we use shared preferences but + now we use datastore which will be more modern way to store such data... but this will also mean + that your previous setting will be + not available anymore. we have decide this break changes, because app settings can be restored + again (in like few minutes). [@JeelDobariya38] + +### Added + +#### Preview Features + +- **Autofill System (Preview Feature)**: added a autofill service to autofill user's credentials on + the fly. [@hexCode63] + +- **Jetpack Compose (Preview Feature)**: added jetpack compose UI & even added a toggle to switch to + this new UI. + but it would be worthless to do so, because it just has a single screen.. *this feature is mainly + for very earlier testing*. [@JeelDobariya38] + +### Changed + +- **MVI Flavored - Clean Architecture**: migrated the codebase to make it more scalable, + extendable & readable. + This will enable us to create better features faster & make a strong base for faster + iteration. [@JeelDobariya38] + +- **Java 21**: migrated the code for passcodes app now compile to java 21. previously it was + compiling to java 11. This should improve performance & efficiency a bit. [@JeelDobariya38] +- **Improved Performance**: Improve performance & better responsiveness of UI (less of density + pixel, more of scalable pixel measurements). [@JeelDobariya38] ## v1.1.1 - Alpha (Sept 11, 2025)
View Internal Details - + ``` Pacakage Name = "com.jeeldobariya.passcodes" Min Android = 8.0 (API level 26) @@ -26,19 +77,19 @@ Release Notes: [docs/release-notes.md](docs/release-notes.md), there you will fi Version Name = "v1.1.1-Alpha" Master Database Version = "v1" ``` -
+
### Fixed -- **Fixed Import Passwords**: fix the bug, that was not let user select csv files from file picker. due to incorrect mimetype in code.. Contributed by [@JeelDobariya] - +- **Fixed Import Passwords**: fixed the bug that was not allowing user to select csv files + from file picker. due to incorrect mimetype in code.. [@JeelDobariya38] ## v1.1.0 - Alpha (Sept 1, 2025)
View Internal Details - + ``` Pacakage Name = "com.jeeldobariya.passcodes" Min Android = 8.0 (API level 26) @@ -47,27 +98,44 @@ Release Notes: [docs/release-notes.md](docs/release-notes.md), there you will fi Version Name = "v1.1.0-Alpha" Master Database Version = "v1" ``` -
+
### Added -- **Improve UI/UX**: improve view password screen, also adjust the button colors.. Contributed by [@JeelDobariya] -- **Add Feature Flaging**: give user a control on whether they wanna latest exprience or stable exprience. add a way for launching preview features without worry about their stablity. Contributed by [@JeelDobariya] -- **Update Checker**: made a basic update checker that help users stay out to date with latest release & also notify user about already reported security vulnerability. Contributed by [@JeelDobariya] -- **Copy Button (preview feature)**: add copy button for copy passwords for easy of use. but as it is potential threat to security, made it a preview feature. Contributed by [@JeelDobariya] -- **G-Passwords Import/Export (preview feature)**: add a import/export feature. which also compatible with google passwords. I have test it with my google password setup. but, I am not sure wether this will run in every edge case or not. So, it a preview feature. Contributed by [@JeelDobariya] +- **Improved UI/UX**: improved view password screen's visual feel, also adjust the button colors a + bit. [@JeelDobariya38] -### Changed +- **Added Feature Flagging**: given user a control on whether they wanna latest experience or stable + experience. added a way for launching preview features without worry about their + stability. [@JeelDobariya38] + +- **Update Checking**: made a basic update checker that help users to stay up to date with latest + release & also notify user about already reported security vulnerability using pre-release + mechanism. [@JeelDobariya38] + +#### Preview Features + +- **Copy Button (preview feature)**: added a copy button for copying passwords for easy of use. but + as it + is potential threat to security, so made it as a preview feature. [@JeelDobariya38] + +- **G-Passwords Import/Export (preview feature)**: added a import/export feature. which is also + compatible with google passwords. I have test it with my google password setup. but, I am not sure + weather this will run in every edge case or not. So, it is a preview feature for + now. [@JeelDobariya38] -- **Mirgated Project**: Migrate project from `JeelDobariya38 (personal)` to `PasscodesApp (my organization)` account. To reflect my long term vision. Contributed by [@JeelDobariya]. +### Notes +- **Official Github Organization (Aug 31, 2025)**: migrate project & repository from + `JeelDobariya38 (personal account)` + to `PasscodesApp (my organization)` for better development and governance of the project. ## v1.0.0 - Stable (Aug 16, 2025)
View Internal Details - + ``` Pacakage Name = "com.jeeldobariya.passcodes" Min Android = 8.0 (API level 26) @@ -76,26 +144,37 @@ Release Notes: [docs/release-notes.md](docs/release-notes.md), there you will fi Version Name = "v1.0.0-Stable" Master Database Version = "v1" ``` +
### Added -- **Localized App**: add language support for English, Chinese, Hindi, Indonesian, Japanese, Korean, German, Spanish, Vietnamese. Contributed by [@JeelDobariya]. -- **Improved UI/UX**: add confirmation dialogs, support for light & dark theme with additional minor changes. Contributed by [@JeelDobariya & @kudanilll]. -- **New Icon**: add new icons to app. Contributed by [@JeelDobariya]. +- **Localized App**: added language translation for English, Chinese, Hindi, Indonesian, Japanese, + Korean, + German, Spanish, Vietnamese. [@JeelDobariya38]. + +- **Improved UI/UX**: added confirmation dialogs for destructive actions, improved support for + light & dark + theme with additional minor changes. [@JeelDobariya38 & @kudanilll]. + +- **New Icon**: rebanded the app as passcodes with a new visual app icon. [@JeelDobariya38]. ### Changed -- **Mirgated Package Name**: Migrate package name from `com.passwordmanager` to `com.jeeldobariya.passcodes`. Contributed by [@JeelDobariya]. -- **Improve Safety By Kotlin Implementaion**: Move from `Java` to `Kotlin` Language. Contributed by [@JeelDobariya]. -- **Improve Data Storing Process**: Move from `SqliteDatabase` to `Room` Libaray for better datastorage. Contributed by [@JeelDobariya]. +- **Migrated Package Name**: migrate package name from `com.passwordmanager` to + `com.jeeldobariya.passcodes`. [@JeelDobariya38]. + +- **Improve Safety By Kotlin Implementation**: move away from `Java` to `Kotlin` + Language. [@JeelDobariya38]. +- **Improve Data Storing Process**: move away from `SqliteDatabase` to `Room` Library for better + datastorage & security. [@JeelDobariya38]. -## v0.1.0 - Alpha (Aug 26, 2024) +## v0.1.0 - Alpha (Aug 26, 2024) [YANKED RELEASE]
View Internal Details - + ``` Pacakage Name = "com.passwordmanager" Min Android = 8.0 (API level 26) @@ -104,14 +183,27 @@ Release Notes: [docs/release-notes.md](docs/release-notes.md), there you will fi Version Name = "0.1.0-Alpha" Master Database Version = "v1" ``` +
### Added -- **App Icon Creation**: Designed and implemented the initial app icon, providing the application with a recognizable visual identity. Contributed by [@HamadaNative]. -- **Basic App Structure**: Established the foundational architecture of the app, including the main entry point and initial setup. Contributed by [@JeelDobariya]. -- **Main Page Development**: Developed the main page of the app, including basic UI components and initial layout. Contributed by [@HamadaNative]. +- **App Icon Creation**: designed and implemented the initial app icon, providing the application + with a recognizable visual identity. [@HamadaNative]. + +- **Basic App Structure**: established the foundational architecture of the app, including the main + entry point and initial setup. [@JeelDobariya38]. + +- **Main Page Development**: developed the main page of the app, including basic UI components and + initial layout. [@JeelDobariya38]. + +- **Basic Password Store**: developed a database to store the passwords data. [@kudanilll]. + +- **Basic Design System**: developed a basic material 2 design system for consistency in app's + feel & look. [@HamadaNative]. ### Notes -- This is the initial alpha release, focused on setting up the basic structure and key visual elements of the app. +- This was the initial alpha pre-release, focusing more on setting up the basic structure and key + visual + elements of the app. (`Proof Of Concept`). diff --git a/core/.gitignore b/core/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/core/.gitignore @@ -0,0 +1 @@ +/build diff --git a/core/build.gradle.kts b/core/build.gradle.kts new file mode 100644 index 00000000..6b94fb57 --- /dev/null +++ b/core/build.gradle.kts @@ -0,0 +1,70 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.jetbrains.kotlin.serialization) +} + +kotlin { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_21) + } +} + +android { + namespace = "com.jeeldobariya.passcodes.core" + compileSdk { + version = release(36) + } + + defaultConfig { + minSdk = 26 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + getByName("release") { + isMinifyEnabled = false + } + + create("staging") { + isMinifyEnabled = false + } + + getByName("debug") { + isMinifyEnabled = false + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + } +} + +dependencies { + implementation(libs.androidx.core.ktx) + implementation(libs.material) + + // Networking/Parsing + implementation(libs.okhttp) + implementation(libs.json) + + // Concurrency (Coroutines Bundle) + implementation(libs.bundles.coroutines) + + // Android Architecture Components (Lifecycle Bundle) + implementation(libs.lifecycle.runtime) + + // Dependency Injection + implementation(libs.koin) + + // Datastore Preferences + implementation(libs.androidx.datastore.preferences) + implementation(libs.kotlinx.serialization.json) + + testImplementation(libs.bundles.unit.test) +} diff --git a/core/consumer-rules.pro b/core/consumer-rules.pro new file mode 100644 index 00000000..e69de29b diff --git a/core/proguard-rules.pro b/core/proguard-rules.pro new file mode 100644 index 00000000..f1b42451 --- /dev/null +++ b/core/proguard-rules.pro @@ -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 diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml new file mode 100644 index 00000000..e1000761 --- /dev/null +++ b/core/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + diff --git a/core/src/main/kotlin/com/jeeldobariya/passcodes/core/datastore/AppSettings.kt b/core/src/main/kotlin/com/jeeldobariya/passcodes/core/datastore/AppSettings.kt new file mode 100644 index 00000000..f39d3c3c --- /dev/null +++ b/core/src/main/kotlin/com/jeeldobariya/passcodes/core/datastore/AppSettings.kt @@ -0,0 +1,18 @@ +package com.jeeldobariya.passcodes.core.datastore + +// please refer to `core/src/main/kotlin/com/jeeldobariya/passcodes/core/feature_flags/FeatureFlagsSettings.kt` for Migration Guide. + +import android.content.Context +import androidx.datastore.dataStore +import com.jeeldobariya.passcodes.core.R +import kotlinx.serialization.Serializable + +val Context.appDatastore by dataStore( + fileName = "app-settings.json", + serializer = AppSettingsSerializer +) + +@Serializable +data class AppSettings( + val theme: Int = R.style.PasscodesTheme_Default, +) diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/utils/AppSettingsSerializer.kt b/core/src/main/kotlin/com/jeeldobariya/passcodes/core/datastore/AppSettingsSerializer.kt similarity index 89% rename from app/src/main/kotlin/com/jeeldobariya/passcodes/utils/AppSettingsSerializer.kt rename to core/src/main/kotlin/com/jeeldobariya/passcodes/core/datastore/AppSettingsSerializer.kt index a8c03f9a..03c78eb3 100644 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/utils/AppSettingsSerializer.kt +++ b/core/src/main/kotlin/com/jeeldobariya/passcodes/core/datastore/AppSettingsSerializer.kt @@ -1,4 +1,4 @@ -package com.jeeldobariya.passcodes.utils +package com.jeeldobariya.passcodes.core.datastore import androidx.datastore.core.Serializer import kotlinx.serialization.SerializationException @@ -6,7 +6,7 @@ import kotlinx.serialization.json.Json import java.io.InputStream import java.io.OutputStream -object AppSettingsSerializer: Serializer { +object AppSettingsSerializer : Serializer { override val defaultValue: AppSettings get() = AppSettings() diff --git a/core/src/main/kotlin/com/jeeldobariya/passcodes/core/di/CoreModule.kt b/core/src/main/kotlin/com/jeeldobariya/passcodes/core/di/CoreModule.kt new file mode 100644 index 00000000..e344dcdf --- /dev/null +++ b/core/src/main/kotlin/com/jeeldobariya/passcodes/core/di/CoreModule.kt @@ -0,0 +1,18 @@ +package com.jeeldobariya.passcodes.core.di + +import com.jeeldobariya.passcodes.core.domain.usecases.CheckForUpdateUseCase +import okhttp3.OkHttpClient +import org.koin.android.ext.koin.androidContext +import org.koin.dsl.module + +val coreModule = module { + + //TODO: It must be turn to single.. If in future it is required by multiple things and not just `CheckForUpdateUseCase()`. + factory { + OkHttpClient() + } + + factory { + CheckForUpdateUseCase(androidContext(), get()) + } +} diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/utils/UpdateChecker.kt b/core/src/main/kotlin/com/jeeldobariya/passcodes/core/domain/usecases/CheckForUpdateUseCase.kt similarity index 59% rename from app/src/main/kotlin/com/jeeldobariya/passcodes/utils/UpdateChecker.kt rename to core/src/main/kotlin/com/jeeldobariya/passcodes/core/domain/usecases/CheckForUpdateUseCase.kt index 560becaf..30f71984 100644 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/utils/UpdateChecker.kt +++ b/core/src/main/kotlin/com/jeeldobariya/passcodes/core/domain/usecases/CheckForUpdateUseCase.kt @@ -1,7 +1,9 @@ -package com.jeeldobariya.passcodes.utils +package com.jeeldobariya.passcodes.core.domain.usecases import android.content.Context +import android.os.Handler import android.widget.Toast +import com.jeeldobariya.passcodes.core.domain.utils.SemVerUtils import okhttp3.Call import okhttp3.Callback import okhttp3.OkHttpClient @@ -9,15 +11,21 @@ import okhttp3.Request import okhttp3.Response import java.io.IOException -object UpdateChecker { - private val client = OkHttpClient() - - fun checkVersion(context: Context, currentVersion: String) { - val appcontext = context.applicationContext - val currentNormalizeVersion = SemVerUtils.normalize(currentVersion) +// TODO: Refactor the code to use ktor client. +@Suppress("RedundantSuspendModifier") +class CheckForUpdateUseCase( + val context: Context, + val client: OkHttpClient +) { + suspend operator fun invoke( + currentVersion: String, + githubReleaseApiUrl: String, + telegramCommunityUrl: String + ) { + val currNormalizedVersion = SemVerUtils.normalize(currentVersion) val request = Request.Builder() - .url(Constant.GITHUB_RELEASE_API_URL) + .url(githubReleaseApiUrl) .build() client.newCall(request).enqueue(object : Callback { @@ -26,7 +34,7 @@ object UpdateChecker { } override fun onResponse(call: Call, response: Response) { - val body = response.body?.string() ?: return + val body = response.body.string() val releases = SemVerUtils.parseReleases(body) var userReleaseFound = false @@ -35,12 +43,12 @@ object UpdateChecker { for (release in releases) { if (release.draft) continue // ignore drafts - if (release.tag == currentNormalizeVersion) { + if (release.tag == currNormalizedVersion) { userReleaseFound = true if (release.prerelease) { showToast( - appcontext, - "⚠️ You are using a PRE-RELEASE ($currentNormalizeVersion). Not safe for use! Join telegram community (${Constant.TELEGRAM_COMMUNITY_URL})" + context, + "⚠️ You are using a PRE-RELEASE ($currNormalizedVersion). Not safe for use! Join telegram community ($telegramCommunityUrl)" ) } } @@ -55,15 +63,15 @@ object UpdateChecker { } latestStable?.let { - if (SemVerUtils.compare(currentNormalizeVersion, it) < 0) { - showToast(appcontext, "New Update available: $it... Vist our website...") + if (SemVerUtils.compare(currNormalizedVersion, it) < 0) { + showToast(context, "New Update available: $it... Visit our website...") } } if (!userReleaseFound) { showToast( - appcontext, - "⚠️ Version ($currentNormalizeVersion) not found on GitHub releases... Join telegram community (${Constant.TELEGRAM_COMMUNITY_URL})" + context, + "⚠️ Version ($currNormalizedVersion) not found on GitHub releases... Join telegram community ($telegramCommunityUrl)" ) } } @@ -71,7 +79,7 @@ object UpdateChecker { } private fun showToast(context: Context, message: String) { - android.os.Handler(context.mainLooper).post { + Handler(context.mainLooper).post { Toast.makeText(context, message, Toast.LENGTH_LONG).show() } } diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/utils/SemVerUtils.kt b/core/src/main/kotlin/com/jeeldobariya/passcodes/core/domain/utils/SemVerUtils.kt similarity index 94% rename from app/src/main/kotlin/com/jeeldobariya/passcodes/utils/SemVerUtils.kt rename to core/src/main/kotlin/com/jeeldobariya/passcodes/core/domain/utils/SemVerUtils.kt index c323dba9..e495d0a8 100644 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/utils/SemVerUtils.kt +++ b/core/src/main/kotlin/com/jeeldobariya/passcodes/core/domain/utils/SemVerUtils.kt @@ -1,4 +1,4 @@ -package com.jeeldobariya.passcodes.utils +package com.jeeldobariya.passcodes.core.domain.utils import org.json.JSONArray @@ -51,9 +51,9 @@ object SemVerUtils { // Cut off pre-release (-...) or build metadata (+...) val cutIndex = clean.indexOfAny(charArrayOf('-', '+')) return if (cutIndex != -1) { - "v" + clean.substring(0, cutIndex) + "v" + clean.take(cutIndex) } else { "v$clean" } } -} +} \ No newline at end of file diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/flags/FeatureFlagsSettings.kt b/core/src/main/kotlin/com/jeeldobariya/passcodes/core/feature_flags/FeatureFlagsSettings.kt similarity index 98% rename from app/src/main/kotlin/com/jeeldobariya/passcodes/flags/FeatureFlagsSettings.kt rename to core/src/main/kotlin/com/jeeldobariya/passcodes/core/feature_flags/FeatureFlagsSettings.kt index 28a6cea4..4cef76a7 100644 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/flags/FeatureFlagsSettings.kt +++ b/core/src/main/kotlin/com/jeeldobariya/passcodes/core/feature_flags/FeatureFlagsSettings.kt @@ -1,4 +1,4 @@ -package com.jeeldobariya.passcodes.flags +package com.jeeldobariya.passcodes.core.feature_flags // This file contains a solution as commented code... ignore it.. if you don't entertain it. diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/flags/FeatureFlagsSettingsSerializer.kt b/core/src/main/kotlin/com/jeeldobariya/passcodes/core/feature_flags/FeatureFlagsSettingsSerializer.kt similarity index 88% rename from app/src/main/kotlin/com/jeeldobariya/passcodes/flags/FeatureFlagsSettingsSerializer.kt rename to core/src/main/kotlin/com/jeeldobariya/passcodes/core/feature_flags/FeatureFlagsSettingsSerializer.kt index 187978c1..92d16f1f 100644 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/flags/FeatureFlagsSettingsSerializer.kt +++ b/core/src/main/kotlin/com/jeeldobariya/passcodes/core/feature_flags/FeatureFlagsSettingsSerializer.kt @@ -1,4 +1,4 @@ -package com.jeeldobariya.passcodes.flags +package com.jeeldobariya.passcodes.core.feature_flags import androidx.datastore.core.Serializer import kotlinx.serialization.SerializationException @@ -6,7 +6,7 @@ import kotlinx.serialization.json.Json import java.io.InputStream import java.io.OutputStream -object FeatureFlagsSettingsSerializer: Serializer { +object FeatureFlagsSettingsSerializer : Serializer { override val defaultValue: FeatureFlagsSettings get() = FeatureFlagsSettings() diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/utils/tempmigration.kt b/core/src/main/kotlin/com/jeeldobariya/passcodes/core/utils/CollectStateWithLifeCycleInXml.kt similarity index 91% rename from app/src/main/kotlin/com/jeeldobariya/passcodes/utils/tempmigration.kt rename to core/src/main/kotlin/com/jeeldobariya/passcodes/core/utils/CollectStateWithLifeCycleInXml.kt index 284e494b..9b41d82c 100644 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/utils/tempmigration.kt +++ b/core/src/main/kotlin/com/jeeldobariya/passcodes/core/utils/CollectStateWithLifeCycleInXml.kt @@ -1,4 +1,4 @@ -package com.jeeldobariya.passcodes.utils +package com.jeeldobariya.passcodes.core.utils import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Lifecycle diff --git a/app/src/main/kotlin/com/jeeldobariya/passcodes/utils/Permissions.kt b/core/src/main/kotlin/com/jeeldobariya/passcodes/core/utils/Permissions.kt similarity index 92% rename from app/src/main/kotlin/com/jeeldobariya/passcodes/utils/Permissions.kt rename to core/src/main/kotlin/com/jeeldobariya/passcodes/core/utils/Permissions.kt index db1e16cc..d73f22df 100644 --- a/app/src/main/kotlin/com/jeeldobariya/passcodes/utils/Permissions.kt +++ b/core/src/main/kotlin/com/jeeldobariya/passcodes/core/utils/Permissions.kt @@ -1,5 +1,8 @@ -package com.jeeldobariya.passcodes.utils +package com.jeeldobariya.passcodes.core.utils +// comment the below code as permission are not used in app. +// currently, but we might require this later.. +/* import android.Manifest import android.app.Activity import android.content.pm.PackageManager @@ -53,3 +56,4 @@ class Permissions(private val activity: Activity) { grantResults[1] == PackageManager.PERMISSION_GRANTED } } +*/ diff --git a/app/src/main/res/values-night/themes.xml b/core/src/main/res/values-night/themes.xml similarity index 97% rename from app/src/main/res/values-night/themes.xml rename to core/src/main/res/values-night/themes.xml index cb79506a..3daf5724 100644 --- a/app/src/main/res/values-night/themes.xml +++ b/core/src/main/res/values-night/themes.xml @@ -2,7 +2,7 @@