Conversation
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: qodo-free-for-open-source-projects[bot] <189517486+qodo-free-for-open-source-projects[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
* Fix icon caching * Fix * style: auto-fix linting and formatting issues * Quality * style: auto-fix linting and formatting issues * Optimize speed * style: auto-fix linting and formatting issues * Revert "style: auto-fix linting and formatting issues" This reverts commit ab9727a. * Revert "Optimize speed" This reverts commit ea53327. * Update nightly.yml * Update README.md * style: auto-fix linting and formatting issues * Unify Flutter icon cache * style: auto-fix linting and formatting issues * Fix icon cache * Migrate to built-in Flutter's design components * Update Flutter * style: auto-fix linting and formatting issues * Fix builds * Fixed icons * style: auto-fix linting and formatting issues * Fix build? * Change app ID to io.github.omeritzics.updatium * style: auto-fix linting and formatting issues * Update README.md * Update README.md * Update README.md * Attempt to fix Material You colors breaking design * Move filter icon to the top * style: auto-fix linting and formatting issues * Move the grid view button to the top * UI improvments * style: auto-fix linting and formatting issues * Update readme * Update readme * Update readme * Fix build * style: auto-fix linting and formatting issues * Fix overflow * style: auto-fix linting and formatting issues * Fix signing problem(?) * Fix build? * Fix * Release build fix * Update Nightly builds * Update Nightly builds * Revert "Release build fix" This reverts commit 257307d. * Revert "Update Nightly builds" This reverts commit 91b8f47. * Fix release build? * Update release.yml * Update release.yml * Update README.md * Update release.yml * UI fix * Update Hebrew * Bump SDK version * Update Hebrew * Fix Waydroid * style: auto-fix linting and formatting issues * style: auto-fix linting and formatting issues * Revert "Fix Waydroid" This reverts commit d879ba1. * Add nightly-signed.yml * Update nightly-signed.yml * Update workflows * Fix * Should fix signed builds * style: auto-fix linting and formatting issues * Update pubspec.lock * Replace flutter_keyboard_visibility * style: auto-fix linting and formatting issues * Replace shared_storage with docman * style: auto-fix linting and formatting issues * Fix typos * style: auto-fix linting and formatting issues * Another fix * style: auto-fix linting and formatting issues * Update dependencies * Fix * Delete .github/workflows/qama-unsigned.yml * Fix? * style: auto-fix linting and formatting issues * Fix errors? * Now it should fix the signing * Another fix * Another fix attempt * Fix nightly.yml * Try to add a different icon for the Nighly builds. #165 * Nightly new branding * Sign Nightly builds by default * Prepare for the new release * A message about unofficial sources * Fix the nightly build * Some bug fixes * style: auto-fix linting and formatting issues * Revert "Fix the nightly build" This reverts commit 9a1d9cd. * Revert "Fix nightly.yml" This reverts commit 0a68335. * Revert "Nightly new branding" This reverts commit 3e141c6. * Revert "Try to add a different icon for the Nighly builds. #165" This reverts commit 02dd713. * Some more fixes * Improve pure black theme * Attempt to fix grid view bug * Material You bug fix * style: auto-fix linting and formatting issues * Update badge style for GitHub release link * Bug fixes * style: auto-fix linting and formatting issues * Selection fix * UX/UI fixes * style: auto-fix linting and formatting issues * Update supported app sources in README * Fix build * style: auto-fix linting and formatting issues * Selection fix #2 * style: auto-fix linting and formatting issues * Fix spacing * Revert "Fix spacing" This reverts commit 1289296. * Add consistent spacing constants to app pages * style: auto-fix linting and formatting issues * Fix duplicate spacing constants compilation errors * Fix height16 scope issue in showChangeLogDialog * style: auto-fix linting and formatting issues * Add Fastlane supply metadata validation step Added a step to validate Fastlane supply metadata in the lint workflow. * Add Fastlane Supply Metadata validation job Added a new job to validate Fastlane Supply Metadata in the lint workflow. * Remove 'go' job from lint workflow Removed the 'go' job and its associated steps from the lint workflow. * Enhance nightly workflow with linting and formatting Add steps to auto-fix linting issues and format code in nightly workflow. * Enhance CI workflow with linting and formatting steps Added steps to auto-fix linting issues and format code in CI workflow. * Add auto-fix linting and formatting steps to workflow Added steps to auto-fix linting issues and format code before committing changes. * Delete .github/workflows/lint.yml * Delete .github/workflows/dependency-review.yml * Fix updateAppIcon method parameter reference error * Fix #168 * Fix icons in the app view page * style: auto-fix linting and formatting issues * style: auto-fix linting and formatting issues * Remove grid view from the code * Re-add grid view from Qama v26.1 * style: auto-fix linting and formatting issues * Fix typo * Fix formatting in localization section of README * Fix grid * Fix design inconsistency * style: auto-fix linting and formatting issues * Fix app.dart * Delete renovate.json * style: auto-fix linting and formatting issues * fix export error * style: auto-fix linting and formatting issues * Quick bug fix * style: auto-fix linting and formatting issues * Add renovate.json * chore(deps): update google/osv-scanner-action action to v2.3.3 * chore(deps): update gradle to v9.3.1 * chore(deps): update plugin org.jetbrains.kotlin.android to v2.3.10 * chore(deps): update actions/github-script action to v8 * chore(deps): update actions/upload-artifact action to v7 * chore(deps): update stefanzweifel/git-auto-commit-action action to v7 * Another bugfix * Update lib/providers/apps_provider.dart Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update BUTTON_MIGRATION_GUIDE.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update lib/examples/refactored_icon_pipeline_example.dart Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update lib/examples/refactored_icon_pipeline_example.dart Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update assets/translations/README.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * chore(deps): update actions/checkout action to v6 * chore(deps): update actions/github-script action to v8 * style: auto-fix linting and formatting issues * Fix workflows * chore(deps): update dependency node to v24 * chore(deps): update actions/setup-node action to v6 * Update translations.yml * chore(deps): update dependency node to v24 * Migrate some design components to the official Flutter ones * 🌐 Add missing translation keys for export functionality * Fix workflow * chore(deps): update actions/checkout action to v6 * style: auto-fix linting and formatting issues * add about (#196) * M3 Expressive update (#194) * M3 Expressive update * Update lib/main.dart Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * commit --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * chore(deps): update stefanzweifel/git-auto-commit-action action to v7 (#198) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update peter-evans/create-pull-request action to v8 (#197) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (14)
📝 WalkthroughWalkthroughAdds a YARA-based malware scanning system and centralized security settings; integrates scans into APK installation with quarantine support, adds localization for scanner UI, updates settings UI and theme styles, removes several Android-specific integrations, and reshapes pubspec dependencies. Changes
Sequence DiagramsequenceDiagram
participant User
participant AppsProvider
participant SecurityProvider as SecuritySettingsProvider
participant YARAScanner
participant FS as File System
participant Logs as Logs Provider
User->>AppsProvider: installApk(apkPath)
AppsProvider->>SecurityProvider: scanAPK(apkPath)
SecurityProvider->>SecurityProvider: Check auto-scan setting
alt Auto-scan disabled
SecurityProvider-->>AppsProvider: non-infected result
else Auto-scan enabled
SecurityProvider->>YARAScanner: scanFile(apkPath)
YARAScanner->>YARAScanner: Ensure rules loaded / update if needed
YARAScanner-->>SecurityProvider: YARAScanResult
alt Infection detected & quarantine enabled
SecurityProvider->>FS: _quarantineFile(apkPath)
FS-->>SecurityProvider: quarantinePath
SecurityProvider->>Logs: Log quarantine/report
else No infection
SecurityProvider->>Logs: Log scan result
end
SecurityProvider-->>AppsProvider: YARAScanResult
end
alt Malware detected
AppsProvider->>FS: Cleanup downloaded files
AppsProvider-->>User: Error (installation blocked)
else No malware
AppsProvider->>AppsProvider: proceed with installation (platform-specific)
AppsProvider-->>User: Installation success
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
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. Comment |
Summary of ChangesHello, 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 application's security posture by integrating a robust in-app malware scanning system using YARA rules. This new capability allows for the automatic detection and handling of malicious APKs, providing users with a safer experience. Alongside this major feature, the project's dependency landscape has been streamlined through the removal of several external packages and updates to existing ones, contributing to a more maintainable and efficient codebase. Highlights
Changelog
Activity
Using Gemini Code AssistThe 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
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 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
|
There was a problem hiding this comment.
Code Review
This pull request introduces a significant new feature: in-app malware scanning powered by YARA. It also includes a substantial refactoring that removes several dependencies and cleans up the codebase. While the new security feature is a great addition, the current implementation of the YARA scanner is fundamentally flawed and does not provide the expected level of security. Additionally, the refactoring appears to have broken core application functionality, such as installing APKs. There are also concerns about resource management and performance that should be addressed.
| Future<List<PackageInfo>> getAllInstalledInfo() async { | ||
| return await pm.getInstalledPackages(flags: packageInfoFlags) ?? []; | ||
| return []; | ||
| } |
There was a problem hiding this comment.
This function, along with getInstalledInfo and installApk, has been stubbed out and no longer interacts with the Android package manager. This effectively removes the application's core functionality of installing and managing apps. For example, installApk now hardcodes code = 'not_implemented', preventing any installations.
This is a critical regression. If this is an intentional part of a larger refactoring, it should be clearly documented. Otherwise, this needs to be fixed before merging.
| } | ||
|
|
||
| /// Main YARA Scanner Class | ||
| class YARAScanner { |
There was a problem hiding this comment.
The current implementation of YARAScanner is not a true YARA engine. It appears to be a custom, simplified string and hex pattern matcher that parses YARA rule files. This is fundamentally different from how the actual YARA engine works, which involves compiling rules into a more efficient format and using advanced pattern matching algorithms.
This implementation is misleading as the feature is advertised as being 'powered by YARA', and it is likely to be ineffective at detecting malware compared to a real YARA engine. This could create a false sense of security for users.
Recommendation: Instead of a custom implementation, please integrate the actual YARA library. This can be done using Flutter's FFI (Foreign Function Interface) to call the native YARA C library. There might also be existing packages on pub.dev that provide these bindings.
| void dispose() { | ||
| // Cancel auto-update timer to prevent memory leaks | ||
| // Note: We don't dispose the singleton here as it might be used by other instances | ||
| // Instead, callers should call YARAScanner.disposeInstance() when the app is shutting down | ||
| } |
There was a problem hiding this comment.
The dispose method does not clean up the Timer created in the YARAScanner singleton for auto-updates. The comment indicates this is intentional, but there is no corresponding call to YARAScanner.disposeInstance() when the application is terminated. This will result in a resource leak, with the timer continuing to run in the background even when it's no longer needed.
Recommendation: The lifecycle of the YARAScanner singleton should be managed properly. The dispose method here should call a method on the scanner to cancel the timer, or there should be a clear mechanism to dispose of the singleton when the app is destroyed.
| } | ||
|
|
||
| /// Scan APK for malware before installation | ||
| Future<bool> _scanAPKForMalware(String apkPath, {List<String>? additionalApkPaths}) async { |
There was a problem hiding this comment.
The _scanAPKForMalware method creates a new instance of SecuritySettingsProvider every time it's called. The provider's creation (SecuritySettingsProvider.create()) involves asynchronous operations and I/O (reading SharedPreferences and getting application directories), making this approach inefficient, especially if scans are frequent.
Recommendation: To improve performance, SecuritySettingsProvider should be managed as a longer-lived object. Consider providing it as a singleton or using a dependency injection framework like provider to manage its lifecycle, so it's created only once.
There was a problem hiding this comment.
🚫 CI Build Failed
The automated build process failed. Please review the build logs and fix the issues before requesting another review.
Next steps:
- Check the build logs for specific errors
- Fix the identified issues
- Push your fixes to this branch
- The CI will automatically re-run
Once the build passes, this review will be dismissed automatically.
There was a problem hiding this comment.
Actionable comments posted: 14
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
lib/providers/settings_provider.dart (1)
421-439:⚠️ Potential issue | 🟠 MajorExport directory selection is effectively broken now.
pickExportDir()no longer persists a new directory, andgetExportDir()now returns whatever URI was last stored without checking that it is still usable.lib/providers/apps_provider.dartandlib/pages/import_export.dartstill depend on both behaviors, so the picker/export UI can appear to work while writes keep using a stale location or fail later.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/providers/settings_provider.dart` around lines 421 - 439, getExportDir currently just parses the stored 'exportDir' string without validating it, and pickExportDir no longer persists a newly picked directory (nor clears it on remove), causing stale or unusable export locations; fix by updating pickExportDir to (a) invoke the platform picker/code-path that obtains a new Uri, persist its string into prefs under 'exportDir' (and clear prefs when remove==true), and return/update any in-memory state, and (b) update getExportDir to validate the stored Uri (e.g., check the Uri parses, and verify existence/writeability or access via the same storage API used for exporting) and if validation fails return null (and clear the stale prefs entry), so callers in apps_provider.dart and import_export.dart always receive a current usable directory via getExportDir and pickExportDir.lib/pages/home.dart (1)
147-259:⚠️ Potential issue | 🟠 MajorThis removes all working
updatium://deep-link handling.
initDeepLinks()no longer reads the initial intent or subscribes to link events, whileandroid/app/src/main/AndroidManifest.xmlstill exposes theupdatiumscheme. Share/import links will now open the app and then be ignored.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/pages/home.dart` around lines 147 - 259, initDeepLinks currently defines interpretLink/goToAddApp/goToExistingApp but never hooks them up to platform intents, so updatium:// links are ignored; restore initial intent reading and a link-event subscription that invokes interpretLink(Uri) for incoming links, and ensure the subscription is cancelled on widget dispose. Specifically, inside initDeepLinks add code to (1) read the initial link/intent and call interpretLink(Uri.parse(...)) if present, (2) subscribe to the link stream (or AppLinks/uni_links equivalent) and call interpretLink for each event, and (3) save and cancel the StreamSubscription on dispose; keep the existing helper functions (goToAddApp, goToExistingApp, interpretLink) and reuse them when handling both initial and subsequent links.pubspec.yaml (1)
22-76:⚠️ Potential issue | 🔴 CriticalIncompatible API usage detected against declared minimums—build will fail.
The lowered minimums are incompatible with the codebase:
- Flutter 3.19.0: Does not include
Color.withValues(added 3.27.0),WidgetStateProperty(3.22.0),PredictiveBackPageTransitionsBuilder(3.22.0), oryear2023theme flags (3.29.0). The repo uses all of these acrosslib/main.dart,lib/pages/settings.dart,lib/pages/app.dart, and elsewhere.- share_plus 7.0.0: Does not support
fileNameOverridesparameter inShare.shareXFiles(...)(added in 10.0.0). Used inlib/pages/apps.dart:1364.- flutter_foreground_task 8.0.0: Does not include
TaskStartercallback orForegroundServiceTypes(both added in 8.9.0). Used inlib/main.dart:119andlib/main.dart:250.Require minimum versions: Flutter ≥3.29.0, share_plus ≥10.0.0, flutter_foreground_task ≥8.9.0.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pubspec.yaml` around lines 22 - 76, Update the package minimums in pubspec.yaml to match APIs used: set the Dart/Flutter SDK constraint to require Flutter ≥3.29.0 (replace the current sdk/flutter lines so Flutter is ">=3.29.0"), bump share_plus to at least ^10.0.0 to get the fileNameOverrides parameter for Share.shareXFiles, and bump flutter_foreground_task to at least ^8.9.0 to get TaskStarter and ForegroundServiceTypes; this aligns the declared minimums with usages of Color.withValues, WidgetStateProperty, PredictiveBackPageTransitionsBuilder, the year2023 theme flags, Share.shareXFiles(fileNameOverrides: ...), TaskStarter, and ForegroundServiceTypes.lib/pages/settings.dart (1)
828-838:⚠️ Potential issue | 🟠 MajorRemove or disable the dead Shizuku toggle.
Both branches force
settingsProvider.useShizuku = false, so this switch can never stay enabled.lib/providers/apps_provider.dartalso rejects the Shizuku path now, which leaves an interactive control with no working behavior behind it.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/pages/settings.dart` around lines 828 - 838, The Switch for Shizuku is dead (both branches set settingsProvider.useShizuku = false) and should be removed or disabled: remove or replace the Switch widget (the Switch and its onChanged handler around Flexible/Text(tr('useShizuku')) and the references to settingsProvider.useShizuku) or make it clearly disabled by setting value: false and onChanged: null and optionally add a subtitle/tooltip explaining it’s unsupported; also remove any dead branching logic that attempted to toggle Shizuku so no unused code referencing settingsProvider.useShizuku remains.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@android/AndroidManifest.xml`:
- Around line 1-4: The top-level android/AndroidManifest.xml is dead config and
duplicates the flutterEmbedding meta-data; remove this duplicate file or move
the <meta-data android:name="flutterEmbedding" android:value="2" /> entry into
the real app manifest used by Gradle (the manifest merged from
android/app/src/main/AndroidManifest.xml under the <application> element) so
only the canonical manifest contains the flutterEmbedding meta-data.
In `@assets/translations/de.json`:
- Around line 31-64: New YARA/security translation keys (e.g.,
"yaraMalwareScanner", "yaraScannerDescription", "enableAutoScan",
"enableAutoScanDescription", "enableAutoUpdate", "enableAutoUpdateDescription",
"updateInterval", "updateIntervalDescription", "threatLevelFilter",
"quarantineInfected", "quarantineInfectedDescription", etc.) were only added to
de.json causing the Translation Management CI to fail; add the same keys to
every locale file under assets/translations that lib/main.dart declares as
supported (not just en/de/fr) — either with proper localized strings or safe
placeholders (English or the de values) so no locale is left missing these keys
— and ensure the JSON structure and commas are valid in each file.
In `@assets/translations/en.json`:
- Around line 31-61: Add the new translation keys introduced in this diff (for
example: "yaraMalwareScanner", "yaraScannerDescription", "securitySettings",
"enableAutoScan", "enableAutoScanDescription", "enableAutoUpdate",
"enableAutoUpdateDescription", "updateInterval", "updateIntervalDescription",
"hours", "threatLevelFilter", "threatLevelFilterDescription", "level1",
"lowThreat", "level2", "mediumThreat", "level3", "highThreat",
"quarantineSettings", "quarantineInfected", "quarantineInfectedDescription",
"viewQuarantine", "viewQuarantineDescription", "databaseInformation",
"lastUpdate", "rulesVersion", "updateNow", "updating",
"rulesUpdatedSuccessfully", "rulesUpdateFailed", "quarantineViewComingSoon")
into every other locale file so the translation-management job no longer reports
missing keys; for each locale add the exact key names with appropriate
translated strings (or sensible placeholder values such as the English text) so
all locales mirror the en.json keys before merging.
- Around line 31-32: The translation copy overstates the
implementation—lib/security/yara_scanner.dart implements a basic custom matcher,
not a full YARA engine—so update the strings for "yaraMalwareScanner" and
"yaraScannerDescription" to remove "Powered by YARA" and "industry-standard"
phrasing and instead describe it as a basic YARA-inspired/custom rule matcher
that provides additional scanning but does not guarantee full YARA compatibility
or 100% detection; make the language accurate and include a short user-facing
disclaimer about limitations.
In `@lib/pages/settings.dart`:
- Around line 916-923: The DropdownMenuItem labels hardcode "hours" causing "1
hours" — update the label generation in the DropdownButton<int> /
DropdownMenuItem<int> map so it uses the correct singular/plural translation
(e.g., call the app's pluralization API or choose tr('hour') when hours == 1 and
tr('hours') otherwise) when building the child Text for each hours value; keep
the existing use of _securityProviderInitialized and
_securityProvider.getUpdateInterval() unchanged while only changing the label
expression.
In `@lib/providers/apps_provider.dart`:
- Around line 500-516: The placeholder implementations of getAllInstalledInfo
and getInstalledInfo break app-detection; replace them with real package-manager
queries: implement getAllInstalledInfo to return the list of installed
PackageInfo objects from the platform package manager and implement
getInstalledInfo(String? packageName, {bool printErr = true}) to look up and
return the PackageInfo for the given packageName (or null if not found),
preserving the existing try/catch and honoring printErr when logging errors;
ensure you use the same PackageInfo type expected downstream and do not return
[]/null unconditionally so loadApps(), version reconciliation, downgrade checks,
and silent-install logic receive real data.
- Around line 2353-2355: The export feature has been short-circuited:
DocMan-related export paths return null (silently no-op) so neither auto-export
nor manual export persist data; restore the original persistence instead of
returning null by removing the early returns in the DocMan export handlers and
invoking the existing persistence/save routine used by the export flow (the same
code path used by import/export persistence), ensuring both the auto-export and
manual export functions call that persistence method and return its result
rather than null.
- Around line 1058-1065: The variable code is declared as int? but is being
assigned the string 'not_implemented'; replace those string assignments by
throwing immediately when installation is unsupported: inside the branches that
reference AndroidPackageInstaller and ShizukuApkInstaller (the blocks guarded by
settingsProvider.useShizuku), throw a descriptive exception (e.g.,
UnsupportedError or InstallError) instead of assigning a sentinel string so
callers never receive a non-int; leave any remaining integer-returning paths and
the subsequent comparisons (code != 0, code != 3) and InstallError(code)
expecting an int intact.
In `@lib/providers/native_provider.dart`:
- Around line 13-17: The loadSystemFont() function currently sets
_systemFontLoaded = true without actually adding or loading any font, causing
'SystemFont' to be undefined and preventing retries; update loadSystemFont()
(and related FontLoader usage) to either 1) call fontLoader.addFont(...) with
the correct asset/ByteData for the system font and then await fontLoader.load(),
or 2) if the system font is no longer supported, remove the fake success path
and clear the useSystemFont flow (avoid setting _systemFontLoaded = true) so
main.dart's theme fallback to 'SystemFont' doesn't silently fail; reference
loadSystemFont, _systemFontLoaded, and the FontLoader('SystemFont') instance
when making the change.
In `@lib/security/security_settings_provider.dart`:
- Around line 78-80: The scanAPK logic never applies the configured threshold
from getThreatLevelFilter(), so result.matches must be filtered by threat level
before deciding to block/quarantine; update the scanAPK function to read int
threshold = getThreatLevelFilter() and compute filteredMatches =
result.matches.where(match => match.severity >= threshold) (or use the correct
property name on the match object), then use filteredMatches for all downstream
decisions and reporting (e.g., blocking/quarantining, notifications, and
returned results) so the threshold setting actually controls which detections
trigger actions; apply the same filter logic to both places where scanAPK
evaluates result.matches.
- Around line 54-76: The setters setAutoUpdateEnabled and setUpdateInterval
currently only replace the config via YARAScanner.getInstance(_config) but do
not reconfigure the running scanner’s timers; after updating _config and
swapping the instance you should reinitialize the scanner so its auto-update
timer is started/stopped with the new settings—call the scanner reconfiguration
routine (e.g., await _scanner.initialize() or the scanner's restart/reconfigure
method) after assigning _scanner in both setAutoUpdateEnabled and
setUpdateInterval so the running schedule reflects the new config.
In `@lib/security/yara_scanner.dart`:
- Around line 116-144: YARARule.fromString currently collapses an entire .yar
file into one synthetic YARARule, merging metadata across multiple rule blocks;
change the API to parse and return all rules found: implement a parser in
YARARule.fromString (or add YARARules.fromString/parseMultiple) that iterates
the file, detects each "rule <name>" block boundary, collects metadata (name,
author, description, tags, content) per rule, and produces a List<YARARule> (or
an Iterable) rather than a single instance; update callers of
YARARule.fromString to handle multiple rules (or provide a convenience wrapper
for single-rule usage) and ensure the rule content for each YARARule contains
only that block's text so scanning/reporting yields one match object per rule.
- Around line 355-390: The scanner currently only extracts `{ ... }` definitions
and always utf8.encodes the extracted text so quoted strings are skipped and hex
falls back never triggers; update the parsing in the loop that builds strings
(referencing ruleLines and strings) and the later block that finds the match
(stringPattern, stringMatch, searchString, searchBytes, rule.content) to
distinguish three cases: 1) quoted strings (starts with " or ') — strip quotes
and use utf8.encode(searchString), 2) brace or token hex sequences (e.g. "{6A
40}" or "6A 40 68") — detect via a regex like r'^[0-9A-Fa-f\s]+' or presence of
braces and parse hex pairs into bytes, and 3) default text — utf8.encode; ensure
the initial extraction also captures quoted string definitions (e.g.
r'\$(\w+)\s*=\s*"([^"]+)"' and similar) so stringPattern/stringMatch will locate
the correct content in rule.content before converting to searchBytes.
- Around line 183-191: initialize() currently only loads rules from disk and
starts the timer which means fresh installs scan with zero rules; after await
_loadRules() check whether any rules were actually loaded (e.g., rules directory
or in-memory rule list is empty) and if so trigger the same immediate update
routine that _startAutoUpdate schedules (invoke the function the timer would
call — the existing rule-fetch/update method used inside _startAutoUpdate)
before returning; keep cancelling _updateTimer and still start the periodic
timer when config.enableAutoUpdate is true so bootstrapped rules are available
for the first scan.
---
Outside diff comments:
In `@lib/pages/home.dart`:
- Around line 147-259: initDeepLinks currently defines
interpretLink/goToAddApp/goToExistingApp but never hooks them up to platform
intents, so updatium:// links are ignored; restore initial intent reading and a
link-event subscription that invokes interpretLink(Uri) for incoming links, and
ensure the subscription is cancelled on widget dispose. Specifically, inside
initDeepLinks add code to (1) read the initial link/intent and call
interpretLink(Uri.parse(...)) if present, (2) subscribe to the link stream (or
AppLinks/uni_links equivalent) and call interpretLink for each event, and (3)
save and cancel the StreamSubscription on dispose; keep the existing helper
functions (goToAddApp, goToExistingApp, interpretLink) and reuse them when
handling both initial and subsequent links.
In `@lib/pages/settings.dart`:
- Around line 828-838: The Switch for Shizuku is dead (both branches set
settingsProvider.useShizuku = false) and should be removed or disabled: remove
or replace the Switch widget (the Switch and its onChanged handler around
Flexible/Text(tr('useShizuku')) and the references to
settingsProvider.useShizuku) or make it clearly disabled by setting value: false
and onChanged: null and optionally add a subtitle/tooltip explaining it’s
unsupported; also remove any dead branching logic that attempted to toggle
Shizuku so no unused code referencing settingsProvider.useShizuku remains.
In `@lib/providers/settings_provider.dart`:
- Around line 421-439: getExportDir currently just parses the stored 'exportDir'
string without validating it, and pickExportDir no longer persists a newly
picked directory (nor clears it on remove), causing stale or unusable export
locations; fix by updating pickExportDir to (a) invoke the platform
picker/code-path that obtains a new Uri, persist its string into prefs under
'exportDir' (and clear prefs when remove==true), and return/update any in-memory
state, and (b) update getExportDir to validate the stored Uri (e.g., check the
Uri parses, and verify existence/writeability or access via the same storage API
used for exporting) and if validation fails return null (and clear the stale
prefs entry), so callers in apps_provider.dart and import_export.dart always
receive a current usable directory via getExportDir and pickExportDir.
In `@pubspec.yaml`:
- Around line 22-76: Update the package minimums in pubspec.yaml to match APIs
used: set the Dart/Flutter SDK constraint to require Flutter ≥3.29.0 (replace
the current sdk/flutter lines so Flutter is ">=3.29.0"), bump share_plus to at
least ^10.0.0 to get the fileNameOverrides parameter for Share.shareXFiles, and
bump flutter_foreground_task to at least ^8.9.0 to get TaskStarter and
ForegroundServiceTypes; this aligns the declared minimums with usages of
Color.withValues, WidgetStateProperty, PredictiveBackPageTransitionsBuilder, the
year2023 theme flags, Share.shareXFiles(fileNameOverrides: ...), TaskStarter,
and ForegroundServiceTypes.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 29b0bea5-5302-4408-9eaf-d47daeb09029
⛔ Files ignored due to path filters (1)
pubspec.lockis excluded by!**/*.lock
📒 Files selected for processing (16)
android/AndroidManifest.xmlassets/translations/de.jsonassets/translations/en.jsonassets/translations/fr.jsonlib/custom_errors.dartlib/main.dartlib/pages/app.dartlib/pages/apps.dartlib/pages/home.dartlib/pages/settings.dartlib/providers/apps_provider.dartlib/providers/native_provider.dartlib/providers/settings_provider.dartlib/security/security_settings_provider.dartlib/security/yara_scanner.dartpubspec.yaml
💤 Files with no reviewable changes (3)
- lib/pages/apps.dart
- lib/pages/app.dart
- lib/custom_errors.dart
| "yaraMalwareScanner": "Automatische Malware-Erkennung (Powered by YARA)", | ||
| "yaraScannerDescription": "Branchenstandardmäßige Malware-Erkennung mit YARA-kompatiblen Regeln für umfassenden Schutz vor Viren, Trojanern und anderen Bedrohungen. Kein Scanner kann 100% Erkennung garantieren, bietet aber starken Schutz vor bekannter Malware. Die Verantwortung für die sichere App-Nutzung liegt letztlich beim Benutzer.", | ||
| "securitySettings": "Sicherheitseinstellungen", | ||
| "xIsTrackOnly": "{} ist nur zur Nachverfolgung", | ||
| "source": "Quelle", | ||
| "app": "App", | ||
| "enableAutoScan": "Automatische Scan aktivieren", | ||
| "enableAutoScanDescription": "Heruntergeladene APKs automatisch auf Malware scannen, vor der Installation", | ||
| "enableAutoUpdate": "Automatische Updates aktivieren", | ||
| "enableAutoUpdateDescription": "Malware-Definitions-Datenbank automatisch aktualisieren", | ||
| "updateInterval": "Update-Intervall", | ||
| "updateIntervalDescription": "Wie oft nach neuen Malware-Definitionen gesucht werden soll", | ||
| "hours": "Stunden", | ||
| "threatLevelFilter": "Bedrohungsstufen-Filter", | ||
| "threatLevelFilterDescription": "Mindestbedrohungsstufe für Warnungen", | ||
| "level1": "Stufe 1", | ||
| "lowThreat": "Niedrige Bedrohung", | ||
| "level2": "Stufe 2", | ||
| "mediumThreat": "Mittlere Bedrohung", | ||
| "level3": "Stufe 3", | ||
| "highThreat": "Hohe Bedrohung", | ||
| "quarantineSettings": "Quarantäne-Einstellungen", | ||
| "quarantineInfected": "Infizierte Dateien quarantänen", | ||
| "quarantineInfectedDescription": "Erkannte Malware zur Sicherheit in Quarantäne verschieben", | ||
| "viewQuarantine": "Quarantäne anzeigen", | ||
| "viewQuarantineDescription": "Quarantänierte Dateien verwalten", | ||
| "databaseInformation": "Datenbank-Informationen", | ||
| "lastUpdate": "Letzte Aktualisierung", | ||
| "rulesVersion": "Regeln-Version", | ||
| "updateNow": "Jetzt aktualisieren", | ||
| "updating": "Aktualisiere...", | ||
| "rulesUpdatedSuccessfully": "Malware-Definitionen erfolgreich aktualisiert", | ||
| "rulesUpdateFailed": "Fehler beim Aktualisieren der Malware-Definitionen", | ||
| "quarantineViewComingSoon": "Quarantäne-Ansicht kommt bald", |
There was a problem hiding this comment.
These new YARA keys still need to land in the rest of assets/translations/.
The Translation Management job is already failing, and lib/main.dart declares many supported locales beyond en/de/fr. Adding the new security keys in only a subset of locale files keeps CI red and leaves the remaining locales on fallback/missing strings.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@assets/translations/de.json` around lines 31 - 64, New YARA/security
translation keys (e.g., "yaraMalwareScanner", "yaraScannerDescription",
"enableAutoScan", "enableAutoScanDescription", "enableAutoUpdate",
"enableAutoUpdateDescription", "updateInterval", "updateIntervalDescription",
"threatLevelFilter", "quarantineInfected", "quarantineInfectedDescription",
etc.) were only added to de.json causing the Translation Management CI to fail;
add the same keys to every locale file under assets/translations that
lib/main.dart declares as supported (not just en/de/fr) — either with proper
localized strings or safe placeholders (English or the de values) so no locale
is left missing these keys — and ensure the JSON structure and commas are valid
in each file.
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (3)
lib/providers/apps_provider.dart (3)
500-516:⚠️ Potential issue | 🔴 CriticalRestore real installed-package queries (placeholders break app state).
getAllInstalledInfo()andgetInstalledInfo()now return[]/nullunconditionally, so installed apps are treated as uninstalled. That breaks install-state reconciliation, downgrade checks, and silent-install eligibility.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/providers/apps_provider.dart` around lines 500 - 516, The placeholders in getAllInstalledInfo() and getInstalledInfo() are breaking app state; restore their real implementations by replacing the empty returns with the actual platform queries: have getAllInstalledInfo() asynchronously fetch and map installed packages into List<PackageInfo> (e.g., using the platform package API originally used in this file) and have getInstalledInfo(String? packageName, {bool printErr = true}) query for a single package by name, returning a PackageInfo or null; keep the existing try/catch behavior, ensure errors are logged when printErr is true, and return the proper types instead of []/null so install-state reconciliation, downgrade checks, and silent-install eligibility work correctly.
1058-1074:⚠️ Potential issue | 🔴 CriticalInstallation path has a hard type error (
int?assignedString).
codeisint?, but both branches assign'not_implemented'(Line 1061, Line 1064). Subsequent integer comparisons andInstallError(code)are incompatible and break this path.#!/bin/bash set -euo pipefail # Verify the mismatched assignments in installApk() sed -n '1056,1076p' lib/providers/apps_provider.dart # Verify InstallError usage/signature context expects numeric code rg -n -C3 'class InstallError|InstallError\(' libSuggested fix
- int? code; - if (!settingsProvider.useShizuku) { - // AndroidPackageInstaller functionality removed - code = 'not_implemented'; - } else { - // ShizukuApkInstaller functionality removed - code = 'not_implemented'; - } + throw UpdatiumError(tr('functionNotImplemented'));🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/providers/apps_provider.dart` around lines 1058 - 1074, The variable code is declared as int? but is being assigned the String 'not_implemented'; change those assignments to an integer sentinel (e.g., define a constant like kNotImplemented = -2 and assign that) so the comparisons (code != 0 && code != 3) and the InstallError(code) call remain type-correct; update any related conditional logic in the same block (the branches that previously set 'not_implemented') to use the integer constant and ensure InstallError is invoked with an int.
2353-2355:⚠️ Potential issue | 🟠 MajorExport is currently a silent no-op in both auto and manual paths.
Both branches return
nullbefore persistence, so export appears available but does nothing.Also applies to: 2373-2374
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@lib/providers/apps_provider.dart`:
- Around line 939-982: The helper _scanAPKForMalware currently returns false for
both infections and scanner failures, losing distinction; change it to return a
structured result (e.g., an enum ScanOutcome { clean, infected, scannerError }
or a small class ScanResult { ScanOutcome outcome; String? message;
List<String>? matches; }) instead of Future<bool>, populate outcome and
diagnostic fields at each exit (primary scan error -> scannerError with error
message, primary scan infected -> infected with match names, additional APK
outcomes set similarly, final successful path -> clean), and update all callers
of _scanAPKForMalware to handle the new structured result so installation flow
and telemetry can differentiate infected vs scanner-unavailable cases.
- Around line 1361-1363: The code throws
UpdatiumError(tr('shizukuNotSupported')) after download/processing has started,
causing wasted network/disk work; move the Shizuku support check earlier into
the preflight path (e.g., add a check in preflightChecks or the function that
runs before downloads) or change the silent-install eligibility function
(isSilentInstallEligible / similar) to return false when Shizuku is unsupported
so the flow never begins the download/processing; update references to
ShizukuApkInstaller removal accordingly and ensure the early check throws or
prevents silent installs before any expensive work starts.
- Around line 1021-1036: Replace the hard-coded translation lookup tr('Security
scan detected malware. Installation blocked for safety.') with a stable i18n key
(for example tr('securityScanBlocked')) in the block that throws UpdatiumError
when _scanAPKForMalware returns false; update the locales/translation resource
files to include the new key mapping to the full sentence for all supported
locales and ensure any tests or callers expecting the old literal are updated to
use the new key.
---
Duplicate comments:
In `@lib/providers/apps_provider.dart`:
- Around line 500-516: The placeholders in getAllInstalledInfo() and
getInstalledInfo() are breaking app state; restore their real implementations by
replacing the empty returns with the actual platform queries: have
getAllInstalledInfo() asynchronously fetch and map installed packages into
List<PackageInfo> (e.g., using the platform package API originally used in this
file) and have getInstalledInfo(String? packageName, {bool printErr = true})
query for a single package by name, returning a PackageInfo or null; keep the
existing try/catch behavior, ensure errors are logged when printErr is true, and
return the proper types instead of []/null so install-state reconciliation,
downgrade checks, and silent-install eligibility work correctly.
- Around line 1058-1074: The variable code is declared as int? but is being
assigned the String 'not_implemented'; change those assignments to an integer
sentinel (e.g., define a constant like kNotImplemented = -2 and assign that) so
the comparisons (code != 0 && code != 3) and the InstallError(code) call remain
type-correct; update any related conditional logic in the same block (the
branches that previously set 'not_implemented') to use the integer constant and
ensure InstallError is invoked with an int.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0ea4faac-9e2a-4049-b368-28e46aaa3113
📒 Files selected for processing (3)
lib/main.dartlib/pages/apps.dartlib/providers/apps_provider.dart
💤 Files with no reviewable changes (1)
- lib/pages/apps.dart
🚧 Files skipped from review as they are similar to previous changes (1)
- lib/main.dart
| /// Scan APK for malware before installation | ||
| Future<bool> _scanAPKForMalware(String apkPath, {List<String>? additionalApkPaths}) async { | ||
| SecuritySettingsProvider? securityProvider; | ||
| try { | ||
| securityProvider = await SecuritySettingsProvider.create(); | ||
| await securityProvider.initialize(); | ||
| final scanResult = await securityProvider.scanAPK(apkPath); | ||
|
|
||
| if (scanResult.error != null) { | ||
| logs.add('Security scan error for primary APK: ${scanResult.error}'); | ||
| return false; | ||
| } | ||
|
|
||
| if (scanResult.isInfected) { | ||
| logs.add( | ||
| 'Security scan detected malware in APK: ${scanResult.matches.map((m) => m.ruleName).join(', ')}', | ||
| ); | ||
| return false; | ||
| } | ||
|
|
||
| if (additionalApkPaths != null) { | ||
| for (final additionalApkPath in additionalApkPaths) { | ||
| final additionalScanResult = await securityProvider.scanAPK(additionalApkPath); | ||
|
|
||
| if (additionalScanResult.error != null) { | ||
| logs.add('Security scan error for additional APK: ${additionalScanResult.error}'); | ||
| return false; | ||
| } | ||
|
|
||
| if (additionalScanResult.isInfected) { | ||
| logs.add('Security scan detected malware in additional APK: ${additionalScanResult.matches.map((m) => m.ruleName).join(', ')}'); | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return true; | ||
| } catch (e) { | ||
| logs.add('Security scan failed: $e'); | ||
| return false; // Block installation on scan failure | ||
| } finally { | ||
| securityProvider?.dispose(); | ||
| } | ||
| } |
There was a problem hiding this comment.
Don’t collapse malware and scan-failure into a single boolean.
This helper returns false for both infection and scanner errors (Line 947 and Line 976), so callers can’t distinguish “infected APK” from “scanner unavailable/error”. Return a structured status so install flow can show correct user messaging and telemetry.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/providers/apps_provider.dart` around lines 939 - 982, The helper
_scanAPKForMalware currently returns false for both infections and scanner
failures, losing distinction; change it to return a structured result (e.g., an
enum ScanOutcome { clean, infected, scannerError } or a small class ScanResult {
ScanOutcome outcome; String? message; List<String>? matches; }) instead of
Future<bool>, populate outcome and diagnostic fields at each exit (primary scan
error -> scannerError with error message, primary scan infected -> infected with
match names, additional APK outcomes set similarly, final successful path ->
clean), and update all callers of _scanAPKForMalware to handle the new
structured result so installation flow and telemetry can differentiate infected
vs scanner-unavailable cases.
| // ShizukuApkInstaller functionality removed | ||
| throw UpdatiumError(tr('shizukuNotSupported')); | ||
| } |
There was a problem hiding this comment.
Shizuku unsupported is detected too late (after expensive work).
Throwing shizukuNotSupported here happens after download/processing has already started, causing avoidable network/disk work and noisy failures. Gate this earlier in the preflight path (or make silent-install eligibility return false when Shizuku install is unsupported).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/providers/apps_provider.dart` around lines 1361 - 1363, The code throws
UpdatiumError(tr('shizukuNotSupported')) after download/processing has started,
causing wasted network/disk work; move the Shizuku support check earlier into
the preflight path (e.g., add a check in preflightChecks or the function that
runs before downloads) or change the silent-install eligibility function
(isSilentInstallEligible / similar) to return false when Shizuku is unsupported
so the flow never begins the download/processing; update references to
ShizukuApkInstaller removal accordingly and ensure the early check throws or
prevents silent installs before any expensive work starts.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Summary by CodeRabbit
New Features
UI/UX
Localization
Removed Features