Skip to content

Bad#349

Merged
omeritzics merged 32 commits into
mainfrom
bad
May 27, 2026
Merged

Bad#349
omeritzics merged 32 commits into
mainfrom
bad

Conversation

@omeritzics
Copy link
Copy Markdown
Owner

@omeritzics omeritzics commented May 27, 2026

Summary by CodeRabbit

  • New Features

    • Improved "Installed apps" picker with better sizing and selection.
  • Improvements

    • Kurdish (Kurmanjî) locale entry updated for better language support.
    • APK size display now reflects your preferred APK selection.
    • Logs and related dialogs now refresh automatically when logs change.
    • F‑Droid metadata handling improved for more reliable author and changelog info.
    • System font loading refined for more stable startup.
  • Chores

    • Version bumped to 26.5.0.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 27, 2026

Warning

Review limit reached

@omeritzics, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 7 minutes and 48 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0e5a1300-d4f8-42ce-9fe2-d3a9e57abee2

📥 Commits

Reviewing files that changed from the base of the PR and between 05ad6d7 and a588cce.

📒 Files selected for processing (1)
  • .github/workflows/ci.yml
📝 Walkthrough

Walkthrough

Release 26.5.0: version bump and CI git identity change; LogsProvider becomes a ChangeNotifier with provider wiring/watch updates; installed-apps dialog constrained; APK size selection tied to preferred index with refresh; F‑Droid author scrape moved before GitLab metadata; native font-load short‑circuited; minor locale and analyzer tweaks.

Changes

Updatium 26.5.0 Update

Layer / File(s) Summary
Version bump and workflow automation
pubspec.yaml, .github/workflows/nightly.yml
Package version updated to 26.5.0+2605261; nightly auto-fix workflow sets git user.name to github-actions[bot] and user.email to github-actions[bot]@users.noreply.github.com`` for automated commits.
LogsProvider & provider wiring
lib/providers/logs_provider.dart, lib/main.dart, lib/pages/settings.dart
LogsProvider now extends ChangeNotifier and calls notifyListeners() after add/clear; app wiring uses ChangeNotifierProvider and LogsDialog uses context.watch to rebuild reactively.
Installed apps dialog & AddApp reformat
lib/pages/add_app.dart
AddApp page refactors provider read formatting and constrains installed-apps dialog content with a SizedBox capped by MediaQuery; async label resolution and selection behavior unchanged.
APK size selection by preferred index
lib/pages/app.dart
Adds _prevPreferredApkIndex, selects APK URL using preferredApkIndex with bounds fallback, sets HEAD User-Agent from getInstalledInfo with a 5s timeout, and refreshes _apkFileSize() on preference change.
F‑Droid metadata flow
lib/app_sources/fdroid.dart
Author extraction is attempted via an initial F‑Droid page scrape before the GitLab fdroiddata request; GitLab parsing now focuses on changelog construction and the catch no longer retries author scraping.
Native font load & MethodChannel tweak
lib/providers/native_provider.dart, lib/providers/settings_provider.dart
loadSystemFont() short-circuits on non-Android and awaits font loader on Android; pickExportDir uses a const MethodChannel with a dot-separated channel name.
Import spacing, locale, analyzer
lib/main.dart, analysis_options.yaml
Adds a blank import line, updates Kurdî locale entry to Locale('en', 'KMR'), and removes the use_build_context_synchronously ignore from analyzer.errors.

🎯 3 (Moderate) | ⏱️ ~20 minutes

A rabbit hops through the code with cheer,
Commits and providers now draw near,
Dialogs sized and APKs picked just right,
F‑Droid falls back when metadata’s slight,
Version twenty-six point five — all set to flight! 🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Bad' is extremely vague and does not meaningfully describe the changeset, which includes multiple substantial changes across various files including locale updates, provider refactoring, APK file size improvements, and method channel modifications. Replace the title with a descriptive summary of the main change, such as 'Refactor LogsProvider to ChangeNotifier and fix locale configuration' or specify the primary objective of these changes.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bad

Warning

Review ran into problems

🔥 Problems

Stopped waiting for pipeline failures after 30000ms. One of your pipelines takes longer than our 30000ms fetch window to run, so review may not consider pipeline-failure results for inline comments if any failures occurred after the fetch window. Increase the timeout if you want to wait longer or run a @coderabbit review after the pipeline has finished.


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.

@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Add installed apps list, fix crashes, and enhance app details display

✨ Enhancement 🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Add "Installed Apps" list feature to quickly populate app search
• Fix app crashes and improve error handling for Android features
• Enhance F-Droid metadata fetching with fallback author extraction
• Display APK file size information on app details page
• Fix locale codes for Indonesian and Kurdish languages
• Update dependencies and improve code quality
Diagram
flowchart LR
  A["User Interface"] -->|"Add Installed Apps Button"| B["Installed Apps Dialog"]
  B -->|"Select App"| C["Pre-fill Search"]
  D["App Details Page"] -->|"Fetch APK Size"| E["HTTP HEAD Request"]
  E -->|"Display"| F["File Size Info"]
  G["Android Features"] -->|"Error Handling"| H["Graceful Fallback"]
  I["F-Droid Source"] -->|"Enhanced Metadata"| J["Author & Changelog"]

Loading

Grey Divider

File Changes

1. lib/app_sources/codeberg.dart 🐞 Bug fix +1/-2

Fix Codeberg repository name extraction

lib/app_sources/codeberg.dart


2. lib/app_sources/fdroid.dart ✨ Enhancement +62/-47

Enhance F-Droid metadata fetching with fallback

lib/app_sources/fdroid.dart


3. lib/main.dart 🐞 Bug fix +19/-10

Fix locale codes and Android edge-to-edge setup

lib/main.dart


View more (12)
4. lib/pages/add_app.dart ✨ Enhancement +67/-2

Add installed apps list dialog feature

lib/pages/add_app.dart


5. lib/pages/app.dart ✨ Enhancement +47/-0

Add APK file size display functionality

lib/pages/app.dart


6. lib/pages/settings.dart 🐞 Bug fix +1/-1

Fix logs provider state management

lib/pages/settings.dart


7. lib/providers/native_provider.dart Error handling +13/-5

Add error handling for system font loading

lib/providers/native_provider.dart


8. lib/providers/settings_provider.dart 🐞 Bug fix +1/-1

Fix SAF method channel identifier

lib/providers/settings_provider.dart


9. .github/workflows/gitguardian.yaml Dependencies +1/-1

Update GitGuardian action to v1.51.0

.github/workflows/gitguardian.yaml


10. .github/workflows/nightly.yml ⚙️ Configuration changes +2/-0

Add git config for GitHub Actions bot

.github/workflows/nightly.yml


11. .github/workflows/release.yml ⚙️ Configuration changes +0/-65

Remove prepare job from release workflow

.github/workflows/release.yml


12. README.md 📝 Documentation +11/-5

Fix typos and add fork comparison information

README.md


13. analysis_options.yaml ⚙️ Configuration changes +6/-0

Add analyzer error suppressions

analysis_options.yaml


14. pubspec.yaml Dependencies +18/-16

Update dependencies and version number

pubspec.yaml


15. assets/translations/en-KMR.json Additional files +0/-0

...

assets/translations/en-KMR.json


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented May 27, 2026

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Watch triggers side effects ✓ Resolved 🐞 Bug ☼ Reliability
Description
In _UpdatiumState.build, changing AppsProvider/LogsProvider/NotificationsProvider from read() to
watch() makes the whole widget rebuild whenever AppsProvider calls notifyListeners(), re-running
BackgroundFetch/foreground-service start/stop logic. This can repeatedly start/stop background
execution and duplicate first-run side effects during normal app state updates.
Code

lib/main.dart[R355-357]

Evidence
The PR changes these providers to watch(), and the same build method contains start/stop side
effects for BackgroundFetch/foreground service, meaning rebuilds can re-trigger those side effects.

lib/main.dart[352-370]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`_UpdatiumState.build()` now listens to `AppsProvider` (and others) via `context.watch()`. Because `build()` contains imperative side effects (starting/stopping BackgroundFetch and the foreground service), any `notifyListeners()` from `AppsProvider` can re-run those side effects and cause thrashing/duplicate work.

### Issue Context
`AppsProvider` notifies for common events (e.g., download progress updates), so this can happen frequently.

### Fix Focus Areas
- lib/main.dart[352-371]

### Suggested fix
- Use `context.read<AppsProvider>()` / `context.read<LogsProvider>()` / `context.read<NotificationsProvider>()` in `build()` unless their values are directly used to render UI.
- If UI needs to react to those providers, wrap only the UI subtrees that need them in `Consumer/Selector`, and keep side-effectful service toggling behind a listener that only reacts to `SettingsProvider` changes (e.g., `Selector<SettingsProvider,int>` on `updateInterval`/`useFGService`, or move to `didChangeDependencies` with explicit change detection).
- Ensure start/stop operations are idempotent (guard with current running state) to avoid repeated calls even when rebuilds happen.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Wrong APK size shown ✓ Resolved 🐞 Bug ≡ Correctness
Description
AppPage always fetches file size for apkUrls[0] instead of using preferredApkIndex, so for apps with
multiple APKs the displayed size may not match the APK that will actually be downloaded/installed.
This produces incorrect user-facing information.
Code

lib/pages/app.dart[R67-75]

Evidence
The new code hardcodes apkUrls[0], while the download path uses preferredApkIndex to select which
APK URL to fetch and install.

lib/pages/app.dart[67-75]
lib/providers/apps_provider.dart[739-765]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The APK size feature always uses the first entry in `apkUrls`, ignoring `preferredApkIndex` (the APK choice used by the download/install logic). For multi-APK apps this can display the wrong size.

### Issue Context
Download/install uses `app.apkUrls[app.preferredApkIndex]`.

### Fix Focus Areas
- lib/pages/app.dart[67-76]
- lib/providers/apps_provider.dart[739-765]

### Suggested fix
- Use `app.app.preferredApkIndex` when selecting the URL to HEAD:
 - `final idx = (app.app.preferredApkIndex >= 0 && app.app.preferredApkIndex < app.app.apkUrls.length) ? app.app.preferredApkIndex : 0;`
 - Fetch size for `apkUrls[idx].value`.
- Optionally refresh `_apkFileSize` when the preferred APK changes (if that can change while the page is open).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. System font retries endlessly ✓ Resolved 🐞 Bug ☼ Reliability
Description
NativeFeatures.loadSystemFont leaves _systemFontLoaded false when getFilePath() returns null or
throws, so the app will retry loading the font on every rebuild. Since main.dart calls
loadSystemFont from the theme-building path, failures can cause repeated IO attempts and repeated
debugPrint noise.
Code

lib/providers/native_provider.dart[R17-28]

Evidence
The font loader is called from a build-time path, and the updated implementation does not set the
loaded flag when the font path is null or when an exception occurs—so it can repeat on each rebuild.

lib/providers/native_provider.dart[15-29]
lib/main.dart[467-473]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`NativeFeatures.loadSystemFont()` only sets `_systemFontLoaded = true` on the success path. When `AndroidSystemFont().getFilePath()` returns null or throws, `_systemFontLoaded` stays false, so callers will keep retrying.

### Issue Context
`main.dart` calls `NativeFeatures.loadSystemFont()` during theme creation when `useSystemFont` is enabled, which can happen on many rebuilds.

### Fix Focus Areas
- lib/providers/native_provider.dart[15-29]
- lib/main.dart[467-473]

### Suggested fix
- Add an explicit platform guard (e.g., only attempt on Android) and/or track an "attempted" flag:
 - Set `_systemFontLoaded = true` after the first attempt (even if it fails), or
 - Introduce `_systemFontLoadAttempted` / `_systemFontLoadFailed` to prevent repeated retries/log spam.
- Consider moving the call out of `build()` into an initialization path triggered only when the setting flips.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Async context lint disabled ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
analysis_options.yaml globally ignores use_build_context_synchronously, so the analyzer will no
longer flag cases where BuildContext is used after an await and the widget might have been disposed.
This increases the likelihood of runtime exceptions and subtle UI bugs slipping into the codebase.
Code

analysis_options.yaml[R10-15]

Evidence
The analyzer configuration in the PR explicitly disables use_build_context_synchronously
project-wide.

analysis_options.yaml[10-16]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The project-wide analyzer setting disables `use_build_context_synchronously`. This removes a key safety net for a common Flutter lifecycle bug pattern (using `context` after `await` when the widget may no longer be mounted).

### Issue Context
The codebase already contains async UI flows; keeping this lint enabled helps catch regressions early.

### Fix Focus Areas
- analysis_options.yaml[10-16]

### Suggested fix
- Remove the global ignore for `use_build_context_synchronously`.
- Where the lint is noisy but safe, fix locally by:
 - checking `if (!context.mounted) return;` after awaits, or
 - restructuring to avoid using `context` after awaits.
- If absolutely necessary, suppress the lint only at specific call sites (single-line `// ignore:`) rather than disabling it project-wide.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Copy link
Copy Markdown

@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 several features and bug fixes, including a new dialog to select from installed apps, APK file size retrieval, improved F-Droid metadata fallback parsing, and robust system font loading. However, several critical issues were identified in the code review: using context.watch instead of context.read on several providers in root and page widgets will cause severe performance degradation and unnecessary rebuilds; changing the MethodChannel name for SAF will break the directory picker on Android; globally ignoring the use_build_context_synchronously lint can hide dangerous bugs; nesting a ListView inside a scrollable AlertDialog is a performance anti-pattern; removing the !hostChanged check on F-Droid metadata queries causes redundant failing requests for custom hosts; and raw http.head requests lack timeouts and standard headers.

Comment thread lib/main.dart Outdated
Comment thread lib/providers/settings_provider.dart Outdated
Comment thread analysis_options.yaml Outdated
Comment thread lib/pages/add_app.dart
Comment thread lib/app_sources/fdroid.dart Outdated
Comment thread lib/pages/add_app.dart Outdated
Comment thread lib/pages/app.dart
Comment on lines +80 to +93
Future<int?> getApkFileSize(String url) async {
try {
final response = await http.head(Uri.parse(url));
if (response.statusCode == 200) {
final contentLength = response.headers['content-length'];
if (contentLength != null) {
return int.tryParse(contentLength);
}
}
} catch (e) {
// Ignore errors, file size will just not be displayed
}
return null;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Using raw http.head without a timeout can cause the app to hang indefinitely if the server is unresponsive. Additionally, some servers (like GitHub) block requests that do not provide a User-Agent header, returning a 403 Forbidden or 400 Bad Request.

To make this more robust, we should add a standard User-Agent header and a reasonable timeout (e.g., 5 seconds).

  Future<int?> getApkFileSize(String url) async {
    try {
      final response = await http.head(
        Uri.parse(url),
        headers: const {'User-Agent': 'Updatium'},
      ).timeout(const Duration(seconds: 5));
      if (response.statusCode == 200) {
        final contentLength = response.headers['content-length'];
        if (contentLength != null) {
          return int.tryParse(contentLength);
        }
      }
    } catch (e) {
      // Ignore errors, file size will just not be displayed
    }
    return null;
  }

omeritzics and others added 3 commits May 27, 2026 05:44
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>
Comment thread lib/main.dart Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
lib/pages/add_app.dart (2)

909-913: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Force URL field refresh when selecting an installed app.

At Line 909, the selection updates userInput but does not bump urlInputKey, so the visible URL field may not reflect the chosen package.

Suggested change
                                 changeUserInput(
                                   app.packageName ?? '',
                                   true,
                                   false,
+                                  updateUrlInput: true,
                                 );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/pages/add_app.dart` around lines 909 - 913, The selection handler calls
changeUserInput(app.packageName ?? '', true, false) but does not force the URL
TextField to rebuild, so the visible URL may not update; after the
changeUserInput call in the installed-app selection branch update the
urlInputKey (e.g. assign a new UniqueKey() or increment whatever key value is
used for the URL field) inside the same state update so the URL TextField tied
to urlInputKey is recreated and reflects the new userInput; ensure you update
urlInputKey in the same widget state (setState / equivalent) so the UI
refreshes.

875-930: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Handle installed-app fetch failures before opening the dialog.

getAllInstalledInfo() is awaited without try/catch. A platform/plugin exception here leaves the action failing without user feedback.

Suggested change
           onPressed: () async {
-            final installedApps = await getAllInstalledInfo();
-            if (!context.mounted) return;
+            List<dynamic> installedApps;
+            try {
+              installedApps = await getAllInstalledInfo();
+            } catch (e) {
+              if (!context.mounted) return;
+              showError(e, context);
+              return;
+            }
+            if (!context.mounted) return;
 
             showDialog(
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/pages/add_app.dart` around lines 875 - 930, The code calls
getAllInstalledInfo() without error handling, so platform/plugin exceptions can
abort the flow and still attempt UI actions; wrap the await
getAllInstalledInfo() call in a try/catch, handle failures by showing a short
user-visible error (e.g., SnackBar or an AlertDialog) and return early if
fetching fails, and only call showDialog when the fetch succeeds; update
references in this block (getAllInstalledInfo, the surrounding onPressed
callback, and later changeUserInput usage) so the dialog/population logic runs
only on a successful fetch.
🧹 Nitpick comments (1)
lib/pages/add_app.dart (1)

143-143: ⚡ Quick win

Use read instead of watch for NotificationsProvider here.

NotificationsProvider is not a Listenable/ChangeNotifier, so watch won’t make this widget react to its internal state mutations; this creates misleading reactivity assumptions at Line 143.

Suggested change
-    NotificationsProvider notificationsProvider = context
-        .watch<NotificationsProvider>();
+    NotificationsProvider notificationsProvider = context
+        .read<NotificationsProvider>();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/pages/add_app.dart` at line 143, Replace the incorrect
.watch<NotificationsProvider>() call with a non-listening read access since
NotificationsProvider is not a Listenable/ChangeNotifier; locate the usage of
.watch<NotificationsProvider>() in add_app.dart (the widget build/context usage)
and change it to context.read<NotificationsProvider>() (or
Provider.of<NotificationsProvider>(context, listen: false)) so the code obtains
the provider without expecting widget reactivity from NotificationsProvider.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/main.dart`:
- Line 65: The Locale entry for Kurdish is incorrect: update the MapEntry
Locale('en', 'KMR') used in supportedLocales (and any forcedLocale logic relying
on fl.toLanguageTag()) to Locale('kmr') so the language tag is "kmr"; then
rename or add the translation asset to match (e.g.,
assets/translations/kmr.json) and update any references that load
assets/translations/en-KMR.json or use "en-KMR" so they point to the new "kmr"
file/name.

In `@lib/pages/settings.dart`:
- Line 1422: The dialog is calling context.watch<LogsProvider>() but
LogsProvider is registered via Provider(create: ...) and is not reactive, so
mutations like LogsProvider.add()/clear() won't trigger rebuilds; either change
the usage to context.read<LogsProvider>() if you only need a one-time fetch
(e.g., in filterLogs() to set logString), or make LogsProvider reactive by
converting it into a ChangeNotifier/ValueNotifier (update its class to extend
ChangeNotifier, call notifyListeners() in add()/clear(), and register it with
ChangeNotifierProvider) so context.watch<LogsProvider>() will rebuild the dialog
on log changes.

In `@pubspec.yaml`:
- Line 19: The pubspec.yaml version build number regresses (currently "version:
26.5.0+260526") which will break Android upgrades because Android versionCode
must always increase; update the version's build number to a value greater than
the prior +2604141 (e.g., bump to +2604142 or higher) so the generated Android
versionCode increases, and ensure the "version: 26.5.0+<new_build>" line is
updated accordingly.

---

Outside diff comments:
In `@lib/pages/add_app.dart`:
- Around line 909-913: The selection handler calls
changeUserInput(app.packageName ?? '', true, false) but does not force the URL
TextField to rebuild, so the visible URL may not update; after the
changeUserInput call in the installed-app selection branch update the
urlInputKey (e.g. assign a new UniqueKey() or increment whatever key value is
used for the URL field) inside the same state update so the URL TextField tied
to urlInputKey is recreated and reflects the new userInput; ensure you update
urlInputKey in the same widget state (setState / equivalent) so the UI
refreshes.
- Around line 875-930: The code calls getAllInstalledInfo() without error
handling, so platform/plugin exceptions can abort the flow and still attempt UI
actions; wrap the await getAllInstalledInfo() call in a try/catch, handle
failures by showing a short user-visible error (e.g., SnackBar or an
AlertDialog) and return early if fetching fails, and only call showDialog when
the fetch succeeds; update references in this block (getAllInstalledInfo, the
surrounding onPressed callback, and later changeUserInput usage) so the
dialog/population logic runs only on a successful fetch.

---

Nitpick comments:
In `@lib/pages/add_app.dart`:
- Line 143: Replace the incorrect .watch<NotificationsProvider>() call with a
non-listening read access since NotificationsProvider is not a
Listenable/ChangeNotifier; locate the usage of .watch<NotificationsProvider>()
in add_app.dart (the widget build/context usage) and change it to
context.read<NotificationsProvider>() (or
Provider.of<NotificationsProvider>(context, listen: false)) so the code obtains
the provider without expecting widget reactivity from NotificationsProvider.
🪄 Autofix (Beta)

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 46db5fce-1b81-4e9e-8485-7b50ea5e8da2

📥 Commits

Reviewing files that changed from the base of the PR and between bd39059 and 8c0d9f3.

📒 Files selected for processing (7)
  • .github/workflows/nightly.yml
  • assets/translations/en-KMR.json
  • lib/main.dart
  • lib/pages/add_app.dart
  • lib/pages/settings.dart
  • lib/providers/settings_provider.dart
  • pubspec.yaml

Comment thread lib/main.dart
Comment thread lib/pages/settings.dart
Comment thread pubspec.yaml Outdated
omeritzics and others added 2 commits May 27, 2026 06:00
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 27, 2026

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Fixes Applied Successfully

Fixed 2 file(s) based on 1 unresolved review comment.

Files modified:

  • lib/main.dart
  • lib/providers/logs_provider.dart

Commit: 19d8aaabec8065d37742eb9f76a4f5538df2d5bb

The changes have been pushed to the bad branch.

Time taken: 2m 29s

coderabbitai Bot and others added 3 commits May 27, 2026 03:04
Fixed 2 file(s) based on 1 unresolved review comment.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
lib/pages/app.dart (1)

68-77: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Prevent stale APK-size writes from out-of-order async responses.

If _fetchApkFileSize() is triggered multiple times quickly (preferred index changes), an older request can finish later and overwrite _apkFileSize with the wrong value.

Suggested fix
 class _AppPageState extends State<AppPage> {
   AppInMemory? prevApp;
   bool updating = false;
   bool _iconRequested = false;
   Future<void>? _iconFuture;
   int? _apkFileSize;
   int? _prevPreferredApkIndex;
+  int _apkSizeRequestId = 0;

   Future<void> _fetchApkFileSize() async {
+    final requestId = ++_apkSizeRequestId;
     var appsProvider = context.read<AppsProvider>();
     AppInMemory? app = appsProvider.apps[widget.appId];
     if (app != null && app.app.apkUrls.isNotEmpty) {
       final idx = (app.app.preferredApkIndex >= 0 && app.app.preferredApkIndex < app.app.apkUrls.length) ? app.app.preferredApkIndex : 0;
       final size = await getApkFileSize(app.app.apkUrls[idx].value);
-      if (mounted) {
+      if (mounted && requestId == _apkSizeRequestId) {
         setState(() {
           _apkFileSize = size;
         });
       }
     }
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/pages/app.dart` around lines 68 - 77, Older async responses from
_fetchApkFileSize can overwrite _apkFileSize if the preferred APK index changes
mid-request; capture the request-specific identity (e.g., store the chosen idx
and the URL string in local variables before awaiting getApkFileSize) and after
the await, before calling setState, verify the app still exists and that its
current preferredApkIndex (or the current URL) still matches the captured value;
only then update _apkFileSize. This ensures out-of-order responses do not write
stale values.
lib/providers/logs_provider.dart (1)

131-142: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Await add(...) in clear() (and avoid duplicate notifyListeners)

LogsProvider.add(...) is async: it awaits the DB insert(...) and then calls notifyListeners(). clear() currently calls add(...) without await and immediately calls notifyListeners(), so listeners can fire before the “clearedNLogs…” entry is actually written (and notifications can occur twice for successful clears). Update clear() to await add(...) and rely on the notification ordering (skip/move the extra notifyListeners() accordingly).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/providers/logs_provider.dart` around lines 131 - 142, The clear() method
calls the async add(...) but doesn't await it and then calls notifyListeners()
again, causing out-of-order notifications and duplicates; update clear() to
await add(plural(...)) so the "clearedNLogsBeforeXAfterY" entry is inserted
before listeners run, and remove or avoid the extra notifyListeners() after the
await (since add(...) already calls notifyListeners()), ensuring a single
notification in the correct order; refer to the clear() and add() methods and
the notifyListeners() calls when making the change.
lib/app_sources/fdroid.dart (1)

141-161: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix missing return in FDroid.getLatestAPKDetails

lib/app_sources/fdroid.dart’s Future<APKDetails> getLatestAPKDetails(...) has no return before it ends (right before the next @override), so it violates the non-nullable return contract and will fail analysis/compile. Add return details; (or otherwise return/throw) before exiting the method.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/app_sources/fdroid.dart` around lines 141 - 161, The method
FDroid.getLatestAPKDetails currently falls through without returning its
APKDetails result; locate the end of the getLatestAPKDetails(...) function (just
before the following `@override`) and add a return of the constructed details
(e.g., return details;) so the Future<APKDetails> always returns a non-null
APKDetails; ensure this occurs after the gitLabSuccess fallback block and inside
any relevant try/catch flow so all code paths return or rethrow.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/providers/native_provider.dart`:
- Around line 33-34: The code unconditionally sets _systemFontLoaded = true,
preventing any future retry after a transient failure; change this so the flag
is only set when font loading actually succeeds (e.g., move the
_systemFontLoaded = true assignment into the success branch of the font-loading
logic or set it after successful return from the load method), and ensure
error/exception paths leave _systemFontLoaded false (or alternatively introduce
a separate _systemFontLoadAttempted/backoff mechanism if you want to limit
immediate retries); locate the assignment to _systemFontLoaded in the
font-loading method (e.g., _loadSystemFonts or the constructor where the diff
appears) and update the control flow accordingly so failures do not permanently
disable retries.

---

Outside diff comments:
In `@lib/app_sources/fdroid.dart`:
- Around line 141-161: The method FDroid.getLatestAPKDetails currently falls
through without returning its APKDetails result; locate the end of the
getLatestAPKDetails(...) function (just before the following `@override`) and add
a return of the constructed details (e.g., return details;) so the
Future<APKDetails> always returns a non-null APKDetails; ensure this occurs
after the gitLabSuccess fallback block and inside any relevant try/catch flow so
all code paths return or rethrow.

In `@lib/pages/app.dart`:
- Around line 68-77: Older async responses from _fetchApkFileSize can overwrite
_apkFileSize if the preferred APK index changes mid-request; capture the
request-specific identity (e.g., store the chosen idx and the URL string in
local variables before awaiting getApkFileSize) and after the await, before
calling setState, verify the app still exists and that its current
preferredApkIndex (or the current URL) still matches the captured value; only
then update _apkFileSize. This ensures out-of-order responses do not write stale
values.

In `@lib/providers/logs_provider.dart`:
- Around line 131-142: The clear() method calls the async add(...) but doesn't
await it and then calls notifyListeners() again, causing out-of-order
notifications and duplicates; update clear() to await add(plural(...)) so the
"clearedNLogsBeforeXAfterY" entry is inserted before listeners run, and remove
or avoid the extra notifyListeners() after the await (since add(...) already
calls notifyListeners()), ensuring a single notification in the correct order;
refer to the clear() and add() methods and the notifyListeners() calls when
making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 294e82a1-2956-4091-a85a-6e49e89a1f54

📥 Commits

Reviewing files that changed from the base of the PR and between 8c0d9f3 and 7b696f4.

📒 Files selected for processing (8)
  • analysis_options.yaml
  • lib/app_sources/fdroid.dart
  • lib/main.dart
  • lib/pages/add_app.dart
  • lib/pages/app.dart
  • lib/providers/logs_provider.dart
  • lib/providers/native_provider.dart
  • pubspec.yaml
💤 Files with no reviewable changes (1)
  • analysis_options.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • pubspec.yaml

Comment thread lib/providers/native_provider.dart Outdated
omeritzics and others added 3 commits May 27, 2026 07:22
Removed the prepare job and its associated steps from the CI workflow.
@omeritzics omeritzics merged commit 0022ac3 into main May 27, 2026
10 checks passed
@omeritzics omeritzics deleted the bad branch May 27, 2026 04:45
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.

1 participant