Skip to content

New Settings and Biometric Auth#137

Merged
trinadhthatakula merged 5 commits intoproductionfrom
master
Feb 28, 2026
Merged

New Settings and Biometric Auth#137
trinadhthatakula merged 5 commits intoproductionfrom
master

Conversation

@trinadhthatakula
Copy link
Copy Markdown
Owner

@trinadhthatakula trinadhthatakula commented Feb 28, 2026

  • Biometric Authentication: Implemented biometric lock functionality, allowing users to secure the app with fingerprint or device credentials. The app now routes through an authentication screen if enabled, with fallback options for errors or un-enrolled biometrics.
  • New Settings Screen: Introduced a dedicated settings screen to manage various app preferences, including theme customization and security options.
  • Enhanced Theming Options: Added comprehensive theme controls, allowing users to select between Light, Dark, or System theme modes, enable AMOLED mode for pure black backgrounds, and toggle dynamic color based on wallpaper (Android 12+).
  • Refactored Installer Logic: Improved the Shizuku and Dhizuku package installer implementations with better error handling and a robust fallback mechanism to the normal installer if privileged installation fails. This also includes a new utility for creating privileged PackageInstallers.
  • UI Component Modernization: Replaced SingleChoiceSegmentedButtonRow with a new, reusable ConnectedButtonGroup composable component across the app (AppListScreen, FreezerScreen, DashboardHeader, AppFilterSheet) for a more consistent and flexible UI.
  • Funding Options Expansion: Updated the project's funding configuration to include Ko-fi and a custom PayPal link, and reflected these changes in the README.md.
  • Build System Updates: Upgraded various dependencies including Android Gradle Plugin (AGP), Material3, KSP, and Coil3, and updated the Gradle wrapper to 9.4.0-rc-1.

trinadhthatakula and others added 4 commits February 24, 2026 23:12
* Update project inspection profiles and build configuration

* **IDE**: Extensively expanded `Project_Default.xml` with numerous Android Lint inspection tools, specifically covering Accessibility, Jetpack Compose, Fragments, and various Google Play policies.
* **Build**: Updated `app/build.gradle.kts` to exclude dependency information from APKs while retaining it in App Bundles.

* chore(deps): bump com.google.devtools.ksp in the maven group (#128)

Bumps the maven group with 1 update: [com.google.devtools.ksp](https://github.com/google/ksp).


Updates `com.google.devtools.ksp` from 2.3.5 to 2.3.6
- [Release notes](https://github.com/google/ksp/releases)
- [Commits](google/ksp@2.3.5...2.3.6)

---
updated-dependencies:
- dependency-name: com.google.devtools.ksp
  dependency-version: 2.3.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump the maven group with 2 updates (#129)

Bumps the maven group with 2 updates: com.android.application and com.android.test.


Updates `com.android.application` from 9.1.0-alpha09 to 9.2.0-alpha01

Updates `com.android.test` from 9.1.0-alpha09 to 9.2.0-alpha01

Updates `com.android.test` from 9.1.0-alpha09 to 9.2.0-alpha01

---
updated-dependencies:
- dependency-name: com.android.application
  dependency-version: 9.2.0-alpha01
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: com.android.test
  dependency-version: 9.2.0-alpha01
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
- dependency-name: com.android.test
  dependency-version: 9.2.0-alpha01
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Revise APK size details and add support options

Updated download sizes and added support development section.

* Add Ko-fi funding option to FUNDING.yml

add ko-fi and patreon

* Clean up project dependencies by removing benchmarking and profiling libraries

* **Build**: Remove unused versions and library definitions for `annotationJvm`, `uiautomator`, `benchmarkMacroJunit4`, `baselineprofile`, and `profileinstaller` from `gradle/libs.versions.toml`.

* Clean up project-level build configuration and plugin definitions

* **Build**: Remove unused `kotlin-android` and `baselineprofile` plugin definitions from `gradle/libs.versions.toml`.
* **Build**: Remove the commented-out `kotlin.android` plugin alias from the top-level `build.gradle.kts`.

* Enhance Shizuku/Dhizuku installer stability and fallbacks

* **Build**: Bump `versionCode` to 1715 and `versionName` to 1.71.5 in `gradle.properties`.
* **Installer**:
    * Implement a silent fallback mechanism in `InstallerRepositoryImpl` that reverts to the system's default `PackageInstaller` if Shizuku or Dhizuku privileged installations fail.
    * Refactor `getDhizukuPackageInstaller` and `getShizukuPackageInstaller` to use `ShizukuPackageInstallerUtils` for better compatibility across API levels and ROMs, avoiding `NoSuchMethodError` on certain devices.
    * Ensure created installation sessions belong to the app's own package name to prevent UID mismatch errors.
    * Add `emitErrors` flag to `performPackageInstallerInstall` to allow internal retries without triggering error UI states prematurely.
* **ShizukuReflector**: Add `createPackageInstallerFor(installerPackageName)` to allow creating privileged installers for specific package identities.
* **IDE**: Clean up `Project_Default.xml` by removing numerous explicit Android Lint inspection rules.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Trinadh Thatakula <YOUR_EMAIL_HERE>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* chore(deps): bump io.coil-kt.coil3:coil-compose in the maven group (#132)

Bumps the maven group with 1 update: [io.coil-kt.coil3:coil-compose](https://github.com/coil-kt/coil).


Updates `io.coil-kt.coil3:coil-compose` from 3.3.0 to 3.4.0
- [Release notes](https://github.com/coil-kt/coil/releases)
- [Changelog](https://github.com/coil-kt/coil/blob/main/CHANGELOG.md)
- [Commits](coil-kt/coil@3.3.0...3.4.0)

---
updated-dependencies:
- dependency-name: io.coil-kt.coil3:coil-compose
  dependency-version: 3.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: maven
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump the maven group across 1 directory with 3 updates (#134)

Bumps the maven group with 3 updates in the / directory: androidx.compose.material3:material3, com.android.application and com.android.test.


Updates `androidx.compose.material3:material3` from 1.5.0-alpha14 to 1.5.0-alpha15

Updates `com.android.application` from 9.2.0-alpha01 to 9.2.0-alpha02

Updates `com.android.test` from 9.2.0-alpha01 to 9.2.0-alpha02

Updates `com.android.test` from 9.2.0-alpha01 to 9.2.0-alpha02

---
updated-dependencies:
- dependency-name: androidx.compose.material3:material3
  dependency-version: 1.5.0-alpha15
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.android.application
  dependency-version: 9.2.0-alpha02
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.android.test
  dependency-version: 9.2.0-alpha02
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
- dependency-name: com.android.test
  dependency-version: 9.2.0-alpha02
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Update Gradle wrapper to 9.4.0-rc-1

* Update `distributionUrl` to Gradle 9.4.0-rc-1 in `gradle-wrapper.properties`.
* Add `distributionSha256Sum` for the new Gradle distribution.

* Add AndroidX Biometric dependency

* **Build**: Add `androidx.biometric:biometric-ktx` version `1.2.0-alpha05` to `gradle/libs.versions.toml`.
* **App**: Include `libs.androidx.biometric` as an implementation dependency in `app/build.gradle.kts`.

* Implement biometric authentication and expanded user preferences

* **Core**: Add `BiometricHelper` utility to check for biometric hardware and authentication capabilities using `androidx.biometric`.
* **Preferences**:
    * Expand `UserPreferences` and `PreferenceRepository` to support `ThemeMode`, `useDynamicColor`, and `biometricLockEnabled`.
    * Refactor `PreferenceRepositoryImpl` to use `runCatching` for safer enum parsing and organize keys into logical groups (App List, Theme, Security).
* **Security UI**:
    * Implement `BiometricScreen` to handle the transition between the system biometric prompt and a custom `BiometricErrorScreen`.
    * Add `AuthState` sealed interface to manage the application's authentication lifecycle (NotRequired, Locked, Unlocked, Error).
    * Use `FragmentActivity` for hosting `BiometricPrompt` and provide a Material Expressive error UI with retry/exit actions.

* Add SettingsViewModel and initial SettingsScreen with ThemeMode domain model

* **Domain**: Add `ThemeMode` enum to represent Light, Dark, and System theme preferences with associated labels.
* **Presentation**:
    * Implement `SettingsViewModel` to manage user preferences (theme mode, dynamic color, and biometric lock) and interface with `BiometricHelper` for hardware capability checks.
    * Create a placeholder `SettingsScreen` composable integrated with Koin for view model injection.

* Add Settings screen and biometric authentication support

* **Navigation**: Enable the `SETTINGS` destination in `AppDestinations.kt` and integrate `SettingsScreen` into the `MainScreen` navigation logic.
* **Security**:
    * Implement `SecurityViewModel` to manage session-based authentication states (`Locked`, `Unlocked`, `Error`, `NotRequired`).
    * Add `BiometricHelper` to the dependency injection `coreModule`.
    * Update `HomeActivity` to conditionally display a `BiometricScreen` based on the current authentication state before granting access to the `MainScreen`.
* **Preferences**: Expand `UserPreferences` to include settings for `themeMode`, `useDynamicColor`, and `biometricLockEnabled`.
* **Dependency Injection**: Register `SettingsViewModel`, `SecurityViewModel`, and `BiometricHelper` in `Modules.kt`.
* **Code Cleanup**: Remove redundant comments regarding Shizuku permission handling in `HomeActivity`.

* Add UI components and building blocks for Settings screen

* **UI Components**: Implement reusable Composable functions for the settings interface:
    * `SettingsHeader`: Displays a header with an icon and "Settings" title.
    * `SettingsSectionLabel` and `SettingsDivider`: Provides visual separation for setting groups.
    * `SettingsRow`: A base layout for setting items with an icon, title, and subtitle.
    * `SettingsSwitchRow`: A specialized row containing a toggle switch.
    * `SettingsInfoRow`: A row for displaying static key-value information.
    * `SettingsLinkRow`: A row with an action button for external links.
    * `EnrollBiometricRow`: A specific action row for directing users to system biometric settings.

* Introduce `ConnectedButtonGroup` component and refactor UI selection controls

* **Components**: Create `ConnectedButtonGroup`, a reusable selection component built on Material 3 Expressive APIs (`ButtonGroup` and `ToggleButton`) that supports animated width transitions and custom item types (Icon, Label, or both).
* **UI Refactoring**: Replace `SingleChoiceSegmentedButtonRow` and `SegmentedButton` with the new `ConnectedButtonGroup` across multiple screens for a more consistent and animated experience:
    * `SettingsScreen`: Updated theme mode selection.
    * `AppListScreen` & `FreezerScreen`: Updated app type switcher (User/System).
    * `DashboardHeader`: Updated app type switcher.
    * `AppFilterSheet`: Updated tab selection (Filters/Sort).
* **Security**: Wrap `BiometricScreen` content in a `Scaffold` and `Box` to ensure proper layout and padding.
* **Navigation**: Fix a duplicate `SettingsScreen` entry in `MainScreen`'s destination logic.
* **Activity**: Update `HomeActivity` to inherit from `FragmentActivity` instead of `ComponentActivity` to support fragment-based APIs (likely for biometric integration).

* Update theme handling in HomeActivity and adjust versioning in gradle.properties

* Update theme settings icon in SettingsScreen

* **UI**: Update the `SettingsRow` for the "Theme" option in `SettingsScreen.kt` to use the new `theme_panel` icon instead of the shield icon.
* **Resources**: Add `app/src/main/res/drawable/theme_panel.xml`, a new vector drawable representing a color palette/theme panel.

* Add AMOLED mode support for pure black background in dark theme

* **UI**: Add "AMOLED Mode" switch to `SettingsScreen` with a description for pure black backgrounds.
* **Theme**: Update `ThorTheme` to override background and surface colors to pure black when `amoledMode` and `darkTheme` are enabled.
* **Domain**: Add `useAmoled` property to `UserPreferences` and define `setUseAmoled` in `PreferenceRepository`.
* **Data**: Implement `USE_AMOLED` DataStore key and persistence logic in `PreferenceRepositoryImpl`.
* **Integration**: Update `SettingsViewModel` to handle AMOLED toggle and `HomeActivity` to pass the preference to the theme engine.

* Update app/src/main/java/com/valhalla/thor/HomeActivity.kt

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* Update app/src/main/java/com/valhalla/thor/presentation/main/MainScreen.kt

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fix review feedback: compilation errors, auth flicker, dead file, Gradle RC (#136)

* Initial plan

* Address all open review comments from Settings page PR

Co-authored-by: trinadhthatakula <33689525+trinadhthatakula@users.noreply.github.com>

* Revert Gradle wrapper back to 9.4.0-rc-1 (9.4 stable not yet released)

Co-authored-by: trinadhthatakula <33689525+trinadhthatakula@users.noreply.github.com>

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: trinadhthatakula <33689525+trinadhthatakula@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Remove distribution SHA-256 sum from Gradle wrapper

* Remove the `distributionSha256Sum` property from `gradle/wrapper/gradle-wrapper.properties`.

* Update app/src/main/java/com/valhalla/thor/presentation/security/BiometricPromptHandler.kt

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update app/src/main/java/com/valhalla/thor/presentation/common/components/ConnectedButtonGroup.kt

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Trinadh Thatakula <YOUR_EMAIL_HERE>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
* **UI**: Remove unused `Spacer`, `width`, and `animateWidth` imports from `ConnectedButtonGroup.kt`.
* **UI**: Remove duplicate `@OptIn` and `@Composable` annotations from the `connectedShapesFor` function in `ConnectedButtonGroup.kt`.
* **Security**: Remove a duplicate `BiometricPromptHandler` object declaration and its associated KDoc in `BiometricPromptHandler.kt`.
Removed Fingerprint Lock from upcoming features and added it to working features.
Copilot AI review requested due to automatic review settings February 28, 2026 09:07
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 28, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch master

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the user experience by introducing new personalization and security features. Users can now customize the app's appearance with detailed theming options and protect access using biometric authentication. Additionally, the underlying package installation logic has been made more resilient, and several UI components have been modernized for improved consistency and maintainability across the application.

Highlights

  • Biometric Authentication: Implemented biometric lock functionality, allowing users to secure the app with fingerprint or device credentials. The app now routes through an authentication screen if enabled, with fallback options for errors or un-enrolled biometrics.
  • New Settings Screen: Introduced a dedicated settings screen to manage various app preferences, including theme customization and security options.
  • Enhanced Theming Options: Added comprehensive theme controls, allowing users to select between Light, Dark, or System theme modes, enable AMOLED mode for pure black backgrounds, and toggle dynamic color based on wallpaper (Android 12+).
  • Refactored Installer Logic: Improved the Shizuku and Dhizuku package installer implementations with better error handling and a robust fallback mechanism to the normal installer if privileged installation fails. This also includes a new utility for creating privileged PackageInstallers.
  • UI Component Modernization: Replaced SingleChoiceSegmentedButtonRow with a new, reusable ConnectedButtonGroup composable component across the app (AppListScreen, FreezerScreen, DashboardHeader, AppFilterSheet) for a more consistent and flexible UI.
  • Funding Options Expansion: Updated the project's funding configuration to include Ko-fi and a custom PayPal link, and reflected these changes in the README.md.
  • Build System Updates: Upgraded various dependencies including Android Gradle Plugin (AGP), Material3, KSP, and Coil3, and updated the Gradle wrapper to 9.4.0-rc-1.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • .github/FUNDING.yml
    • Added Ko-fi and custom PayPal funding links.
  • README.md
    • Updated APK size estimates to reflect current state.
    • Added 'Fingerprint Lock' and 'Themes' to the list of working features.
    • Included 'Dhizuku Support (testing)' in working features.
    • Introduced a new 'Support Development' section with links to Patreon, Buy Me a Coffee, and PayPal.
  • app/build.gradle.kts
    • Added androidx.biometric dependency for biometric authentication.
    • Configured dependenciesInfo to exclude from APK but include in bundle.
    • Updated various library versions.
  • app/src/main/java/com/valhalla/thor/HomeActivity.kt
    • Changed HomeActivity to extend FragmentActivity to support biometric prompts.
    • Integrated SecurityViewModel and SettingsViewModel for managing app state.
    • Implemented biometric authentication flow at app launch, displaying BiometricScreen if required.
    • Applied theme preferences (darkTheme, dynamicColor, amoledMode) from SettingsViewModel to ThorTheme.
  • app/src/main/java/com/valhalla/thor/data/repository/InstallerRepositoryImpl.kt
    • Removed direct IPackageManager import.
    • Refactored getDhizukuPackageInstaller and added getShizukuPackageInstaller to use ShizukuPackageInstallerUtils for privileged installer creation.
    • Modified performPackageInstallerInstall to include an emitErrors parameter, allowing silent fallbacks for privileged installers.
    • Improved error handling for session creation and opening within performPackageInstallerInstall.
  • app/src/main/java/com/valhalla/thor/data/repository/PreferenceRepositoryImpl.kt
    • Expanded Keys object to include new preferences for theme (THEME_MODE, USE_DYNAMIC_COLOR, USE_AMOLED) and security (BIOMETRIC_LOCK).
    • Updated userPreferences flow to map and retrieve new theme and security settings.
    • Added suspend functions (setThemeMode, setDynamicColor, setUseAmoled, setBiometricLock) to update new preferences.
  • app/src/main/java/com/valhalla/thor/data/security/BiometricHelper.kt
    • Added a new class BiometricHelper to provide a thin wrapper around BiometricManager for checking biometric capabilities.
  • app/src/main/java/com/valhalla/thor/data/source/local/shizuku/ShizukuReflector.kt
    • Added createPackageInstallerFor method to create a privileged PackageInstaller for a specific package name, leveraging ShizukuPackageInstallerUtils.
  • app/src/main/java/com/valhalla/thor/di/Modules.kt
    • Registered BiometricHelper as a Koin singleton.
    • Registered SettingsViewModel and SecurityViewModel as Koin ViewModels.
  • app/src/main/java/com/valhalla/thor/domain/model/ThemeMode.kt
    • Added a new enum class ThemeMode (LIGHT, DARK, SYSTEM) with a label() function.
  • app/src/main/java/com/valhalla/thor/domain/model/UserPreferences.kt
    • Added new fields to UserPreferences data class: themeMode, useDynamicColor, useAmoled, and biometricLockEnabled.
  • app/src/main/java/com/valhalla/thor/domain/repository/PreferenceRepository.kt
    • Added new suspend functions to the PreferenceRepository interface for managing theme (setThemeMode, setDynamicColor, setUseAmoled) and security (setBiometricLock) preferences.
  • app/src/main/java/com/valhalla/thor/presentation/appList/AppListScreen.kt
    • Replaced SingleChoiceSegmentedButtonRow with the new ConnectedButtonGroup for app type switching.
  • app/src/main/java/com/valhalla/thor/presentation/common/components/ConnectedButtonGroup.kt
    • Added a new composable ConnectedButtonGroup for creating single-select segmented button groups with icon, label, or icon-with-label items.
  • app/src/main/java/com/valhalla/thor/presentation/freezer/FreezerScreen.kt
    • Replaced SingleChoiceSegmentedButtonRow with the new ConnectedButtonGroup for app source switching.
  • app/src/main/java/com/valhalla/thor/presentation/home/AppDestinations.kt
    • Added SETTINGS as a new AppDestinations entry.
  • app/src/main/java/com/valhalla/thor/presentation/home/components/DashboardHeader.kt
    • Replaced SingleChoiceSegmentedButtonRow with the new ConnectedButtonGroup for app type switching.
  • app/src/main/java/com/valhalla/thor/presentation/main/MainScreen.kt
    • Integrated SettingsScreen into the navigation composable, accessible via AppDestinations.SETTINGS.
  • app/src/main/java/com/valhalla/thor/presentation/security/AuthState.kt
    • Added a new sealed interface AuthState to define the app's authentication states (NotRequired, Locked, Unlocked, Error).
  • app/src/main/java/com/valhalla/thor/presentation/security/BiometricPromptHandler.kt
    • Added a new internal object BiometricPromptHandler (currently minimal) for biometric prompt interactions.
  • app/src/main/java/com/valhalla/thor/presentation/security/BiometricScreen.kt
    • Added a new composable BiometricScreen to handle biometric authentication, displaying a system prompt or an error screen with retry/exit options.
  • app/src/main/java/com/valhalla/thor/presentation/security/SecurityViewModel.kt
    • Added a new SecurityViewModel to manage the app's biometric authentication state, including session authentication, error handling, and retry logic.
  • app/src/main/java/com/valhalla/thor/presentation/settings/SettingsScreen.kt
    • Added a new composable SettingsScreen to display and manage app settings, including appearance (theme, AMOLED, dynamic color) and security (biometric lock) options.
    • Implemented logic to guide users to device settings if biometric hardware is present but not enrolled.
  • app/src/main/java/com/valhalla/thor/presentation/settings/SettingsViewModel.kt
    • Added a new SettingsViewModel to expose user preferences and provide functions to update theme and biometric lock settings, leveraging BiometricHelper.
  • app/src/main/java/com/valhalla/thor/presentation/theme/Theme.kt
    • Modified ThorTheme composable to accept an amoledMode parameter.
    • Applied a pure black background and surface color when darkTheme and amoledMode are both true.
  • app/src/main/java/com/valhalla/thor/presentation/widgets/AppList.kt
    • Replaced SingleChoiceSegmentedButtonRow with the new ConnectedButtonGroup in the AppFilterSheet.
  • app/src/main/res/drawable/theme_panel.xml
    • Added a new vector drawable for a theme panel icon.
  • build.gradle.kts
    • Removed the kotlin-android plugin alias.
    • Updated Android Gradle Plugin (AGP) version.
  • gradle.properties
    • Commented out ksp.use.k2 property.
    • Updated initialVersionCode, versionCode, and versionName.
  • gradle/libs.versions.toml
    • Updated agp to 9.2.0-alpha02.
    • Added biometric library version 1.2.0-alpha05.
    • Updated ksp to 2.3.6.
    • Updated material3 to 1.5.0-alpha15.
    • Updated coil3 to 3.4.0.
    • Removed unused benchmarking and profiling dependencies (annotationJvm, uiautomator, benchmarkMacroJunit4, baselineprofile, profileinstaller).
  • gradle/wrapper/gradle-wrapper.properties
    • Updated Gradle distribution URL to gradle-9.4.0-rc-1-bin.zip.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces significant new features, including a comprehensive settings screen, theme customization with an AMOLED mode, and biometric authentication. The implementation is well-structured, introducing new ViewModels, state management for security, and reusable UI components like ConnectedButtonGroup. The installer logic has also been made more robust with a fallback mechanism. The code quality is generally high, but there are a few areas for improvement regarding code cleanup and best practices detailed in the comments.

Comment on lines +328 to +338
fun createPackageInstallerFor(installerPackageName: String): PackageInstaller {
val iPackageInstaller = ShizukuPackageInstallerUtils.getPrivilegedPackageInstaller()
val root = try { rikka.shizuku.Shizuku.getUid() == 0 } catch (_: Exception) { false }
val userId = if (root) android.os.Process.myUserHandle().hashCode() else 0

return ShizukuPackageInstallerUtils.createPackageInstaller(
iPackageInstaller,
installerPackageName,
userId
)
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The new function createPackageInstallerFor appears to be unused in the project. Furthermore, its logic is almost identical to the getShizukuPackageInstaller function in InstallerRepositoryImpl. This introduces code duplication and dead code. To improve maintainability, this unused function should be removed.

SettingsHeader()

// ── APPEARANCE ──────────────────────────────────────────────────────
SettingsSectionLabel("Appearance")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The string "Appearance" is hardcoded. For better maintainability and to support localization in the future, it's recommended to extract UI strings into strings.xml resource files and reference them using stringResource(R.string.your_string_id). This applies to other hardcoded strings in this file as well.

Suggested change
SettingsSectionLabel("Appearance")
SettingsSectionLabel(stringResource(R.string.settings_appearance))

…epositoryImpl.kt

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@trinadhthatakula trinadhthatakula merged commit 50bddb1 into production Feb 28, 2026
1 of 2 checks passed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new in-app Settings experience (theme + security) and introduces biometric authentication gating at app launch, along with UI component refactors and build/dependency updates.

Changes:

  • Add Settings screen + persistence for theme mode, dynamic color, AMOLED mode, and biometric-lock preference (DataStore).
  • Add biometric lock gate (auth state VM + biometric prompt/error UI) and wire it into HomeActivity.
  • Introduce ConnectedButtonGroup and replace SegmentedButton usage across multiple screens; update Gradle/versions and installer fallback logic.

Reviewed changes

Copilot reviewed 30 out of 31 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
gradle/wrapper/gradle-wrapper.properties Updates Gradle wrapper distribution URL.
gradle/libs.versions.toml Updates version catalog (AGP/KSP/material3/coil) and adds Biometric dependency entry; removes some catalog entries.
gradle.properties Disables ksp.use.k2 and bumps app version code/name.
build.gradle.kts Adjusts top-level plugin aliases (comment removal).
app/src/main/res/drawable/theme_panel.xml Adds a new theme-related vector drawable for Settings UI.
app/src/main/java/com/valhalla/thor/presentation/widgets/AppList.kt Replaces segmented tabs in filter sheet with ConnectedButtonGroup.
app/src/main/java/com/valhalla/thor/presentation/theme/Theme.kt Adds AMOLED theme override support in ThorTheme.
app/src/main/java/com/valhalla/thor/presentation/settings/SettingsViewModel.kt New VM to expose preferences + update theme/security settings.
app/src/main/java/com/valhalla/thor/presentation/settings/SettingsScreen.kt New Settings UI with theme controls, dynamic color, AMOLED, biometric lock, and about links.
app/src/main/java/com/valhalla/thor/presentation/security/SecurityViewModel.kt New VM that derives AuthState from preferences/session/error.
app/src/main/java/com/valhalla/thor/presentation/security/BiometricScreen.kt New biometric prompt + error UI and prompt orchestration.
app/src/main/java/com/valhalla/thor/presentation/security/BiometricPromptHandler.kt Adds placeholder handler object for biometric interactions.
app/src/main/java/com/valhalla/thor/presentation/security/AuthState.kt Defines auth gate state model for biometric lock flow.
app/src/main/java/com/valhalla/thor/presentation/main/MainScreen.kt Adds Settings destination rendering.
app/src/main/java/com/valhalla/thor/presentation/home/components/DashboardHeader.kt Replaces segmented app-type switcher with ConnectedButtonGroup.
app/src/main/java/com/valhalla/thor/presentation/home/AppDestinations.kt Enables Settings destination in bottom navigation.
app/src/main/java/com/valhalla/thor/presentation/freezer/FreezerScreen.kt Replaces segmented app-type switcher with ConnectedButtonGroup.
app/src/main/java/com/valhalla/thor/presentation/common/components/ConnectedButtonGroup.kt Adds reusable connected toggle button group component.
app/src/main/java/com/valhalla/thor/presentation/appList/AppListScreen.kt Replaces segmented app-type switcher with ConnectedButtonGroup.
app/src/main/java/com/valhalla/thor/domain/repository/PreferenceRepository.kt Extends preferences API for theme + security settings.
app/src/main/java/com/valhalla/thor/domain/model/UserPreferences.kt Adds theme/security fields to preferences domain model.
app/src/main/java/com/valhalla/thor/domain/model/ThemeMode.kt Adds ThemeMode enum for theme selection.
app/src/main/java/com/valhalla/thor/di/Modules.kt Wires new VMs and BiometricHelper into Koin modules.
app/src/main/java/com/valhalla/thor/data/source/local/shizuku/ShizukuReflector.kt Adds privileged PackageInstaller creation helper; tweaks uninstall flow block.
app/src/main/java/com/valhalla/thor/data/security/BiometricHelper.kt Adds biometric capability helper wrapper around BiometricManager.
app/src/main/java/com/valhalla/thor/data/repository/PreferenceRepositoryImpl.kt Persists new theme/security preferences in DataStore and maps them to domain.
app/src/main/java/com/valhalla/thor/data/repository/InstallerRepositoryImpl.kt Adds privileged-installer fallbacks and refactors Shizuku/Dhizuku install handling.
app/src/main/java/com/valhalla/thor/HomeActivity.kt Applies theme preferences + gates app entry with biometric auth state.
app/build.gradle.kts Adds Biometric dependency and configures dependenciesInfo.
README.md Documents new features (fingerprint lock, themes) and adds support/donation section.
.github/FUNDING.yml Updates funding links (Ko-fi + PayPal custom).
Comments suppressed due to low confidence (1)

app/src/main/java/com/valhalla/thor/data/repository/InstallerRepositoryImpl.kt:37

  • shizukuReflector is now injected but never used (only suppressed). This adds unnecessary DI wiring and can confuse future maintenance. Remove the constructor parameter and update the Koin module wiring accordingly, or start using it (e.g., via createPackageInstallerFor() if that’s the intent).
class InstallerRepositoryImpl(
    private val context: Context,
    private val eventBus: InstallerEventBus,
    private val rootGateway: RootSystemGateway,
    private val shizukuReflector: ShizukuReflector
) : InstallerRepository {

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-rc-1-bin.zip
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wrapper is being bumped to a Gradle release-candidate (9.4.0-rc-1). RC tooling can be unstable and may break CI/reproducible builds unexpectedly. Prefer pinning the wrapper to the latest stable Gradle distribution unless there is a concrete requirement for the RC.

Copilot uses AI. Check for mistakes.
Comment on lines +77 to +81
checked = index == selectedIndex,
onCheckedChange = { checked -> if (checked) onItemSelected(index) },
modifier = Modifier.animateWidth(interactionSource),
shapes = connectedShapesFor(index, lastIndex),
interactionSource = interactionSource,
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modifier.animateWidth(interactionSource) is used but there is no import or local definition for animateWidth, so this will be an unresolved reference at compile time. Add the correct import for the Material3 expressive animateWidth modifier (or replace this call with the intended animation modifier).

Copilot uses AI. Check for mistakes.
Comment on lines +101 to +117
// Create a PackageInstaller using Dhizuku's binder wrapper but make the installer package
// be this app's package name so created sessions belong to the app UID (avoids UID mismatch).
private fun getDhizukuPackageInstaller(): PackageInstaller {
val binder = SystemServiceHelper.getSystemService("package")
val wrappedBinder = DhizukuAPI.binderWrapper(binder)
val ipm = IPackageManager.Stub.asInterface(ShizukuBinderWrapper(wrappedBinder))
val ipi = ipm.packageInstaller
val privilegedIpi = android.content.pm.IPackageInstaller.Stub.asInterface(ShizukuBinderWrapper(ipi.asBinder()))

// Prefer using the existing Shizuku helper which returns a privileged IPackageInstaller.
// This avoids calling IPackageManager.getPackageInstaller() directly (which may not exist
// on some ROMs / API versions and caused NoSuchMethodError).
try {
val iPackageInstaller = ShizukuPackageInstallerUtils.getPrivilegedPackageInstaller()
val root = try { rikka.shizuku.Shizuku.getUid() == 0 } catch (_: Exception) { false }
val userId = if (root) android.os.Process.myUserHandle().hashCode() else 0
val installerPackageName = context.packageName

return ShizukuPackageInstallerUtils.createPackageInstaller(
iPackageInstaller,
installerPackageName,
userId
)
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getDhizukuPackageInstaller() is currently using ShizukuPackageInstallerUtils, which wraps the PackageManager binder using ShizukuBinderWrapper. That won’t work in Dhizuku mode and effectively disables/breaks the Dhizuku install path (it will always throw and fall back to the normal installer). Rework this to obtain an IPackageInstaller via Dhizuku’s binder wrapper/API (similar to the previous approach / DhizukuHelper) so InstallMode.DHIZUKU actually uses Dhizuku.

Copilot uses AI. Check for mistakes.
Comment on lines +115 to +116
// No credentials enrolled — fail open so user is never locked out.
onAuthenticated()
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For BIOMETRIC_ERROR_NONE_ENROLLED, the code calls onAuthenticated() (fail-open). If the user enabled “Biometric Lock” and later removes biometrics/device credential, this bypasses the lock entirely, undermining the feature. Instead, treat this as a locked/error state (e.g., show an error with a link to enroll credentials, or disable the preference and require explicit user action).

Suggested change
// No credentials enrolled — fail open so user is never locked out.
onAuthenticated()
// No biometrics or device credentials enrolled — keep locked and require user action.
onError("No biometric or device credential is enrolled. Please enroll one in system settings to use biometric lock.")

Copilot uses AI. Check for mistakes.
Comment on lines +222 to +223
// Check if package still has updates; value intentionally ignored here
(updatedPackageInfo.applicationInfo!!.flags and ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block computes whether the app is still an updated system app but discards the result, so it has no effect and is misleading. Either remove this check entirely or use the result (e.g., log it or return it / branch on it) to justify why it exists.

Suggested change
// Check if package still has updates; value intentionally ignored here
(updatedPackageInfo.applicationInfo!!.flags and ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0
// Check if package still has updates and log the result
val stillUpdatedSystemApp =
(updatedPackageInfo.applicationInfo!!.flags and ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0
Logger.d(
"ShizukuReflector",
"Package $packageName still updated system app after uninstall: $stillUpdatedSystemApp"
)

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants