Skip to content

Add plugin update support in Plugins settings tab - #4595

Open
puk06 wants to merge 4 commits into
Flow-Launcher:devfrom
puk06:feat/plugin-updates-in-plugins-tab
Open

Add plugin update support in Plugins settings tab#4595
puk06 wants to merge 4 commits into
Flow-Launcher:devfrom
puk06:feat/plugin-updates-in-plugins-tab

Conversation

@puk06

@puk06 puk06 commented Jul 29, 2026

Copy link
Copy Markdown

Summary

Add plugin update support directly in the Plugins settings tab, making it easy to check for and apply plugin updates without navigating to the Plugin Store tab.

Changes

New Features

  • Auto-check on tab open: Silently checks for plugin updates when navigating to the Plugins tab (once per session)
  • Update badges: Shows vX.X.X → vY.Y.Y version info on plugin cards when an update is available
  • Per-plugin "Update" button: Each plugin card shows an accent-styled "Update" button when an update is available
  • "Check for updates" button: Added to the Plugins tab toolbar (using the same sync icon as the Plugin Store)
  • "Update All" button: Appears in the toolbar when updates are available, triggers batch update via PluginUpdateWindow

File Changes

File Description
PluginViewModel.cs Added UpdateInfo, HasUpdate, NewVersion, UpdateButtonVisibility properties and UpdatePluginCommand
PluginInstaller.cs Changed return type of UpdatePluginAndCheckRestartAsync from Task to Task to report update success. Replaced lexicographic string.Compare with semantic version comparison via SemanticVersioning.Version. Added IsUpdateAvailable helper method
SettingsPanePluginsViewModel.cs Added CheckPluginUpdatesCommand, UpdateAllPluginsCommand, CheckForUpdatesSilentlyAsync. Refactored shared logic into CheckForUpdatesCoreAsync()
SettingsPanePlugins.xaml Added "Check for updates" and "Update All" buttons to the toolbar
SettingsPanePlugins.xaml.cs Call CheckForUpdatesSilentlyAsync in OnNavigatedTo
InstalledPluginDisplay.xaml Added version update display (vX.X.X → vY.Y.Y) and per-plugin "Update" button

How It Works

  1. Auto : Opening the Plugins tab triggers a silent update check (once per session)
  2. Manual : Click the reflesh toolbar button to check for updates at any time
  3. Individual update : Click the "Update" button on any plugin card with a pending update
  4. Batch update : When updates are available, click the "Update plugins" toolbar button to update all at once

Summary by cubic

Adds plugin update checks and actions directly in the Plugins tab. Shows available updates, lets you update one or all plugins, and keeps counts and badges in sync only after successful updates.

Summary of changes

  • Changed: Version comparison now uses SemanticVersioning.Version; opening the Plugins tab runs a silent update check once per session, and on failure we log, reset the guard, and allow retry; update flow returns a success flag; per‑plugin badges clear only on successful update; toolbar update count and “Update All” visibility refresh via a view‑model event on update state changes.
  • Added: Toolbar “Check for updates” button; “Update All” button (only when updates exist) via PluginUpdateWindow; per‑plugin version badge (vX → vY) and “Update” button; commands/state for check, batch update, per‑plugin update, and a shared update‑check routine; bindings for update count and visibility.
  • Removed: None.
  • Memory: Negligible. Stores a small UpdateInfo per plugin only when an update is available; no new persistent caches.
  • Security: Uses existing manifest fetch and installer paths; no new permissions or execution paths; silent checks hit the existing endpoint; failures are logged.
  • Tests: No new unit tests.

Release Note
You can now see and install plugin updates directly from the Plugins tab, including updating all plugins at once.

Written for commit eed303f. Summary will update on new commits.

Review in cubic

- Auto-check for updates silently when navigating to Plugins tab
- Show update badge (v1.0.0 → v2.0.0) on plugin cards with available updates
- Add per-plugin "Update" button in the plugin display header
- Add "Check for updates" button in Plugins tab toolbar
- Add "Update All" button that appears when updates are available
@github-actions github-actions Bot added this to the 2.2.0 milestone Jul 29, 2026
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The plugin settings page now checks plugin manifests, tracks available updates, displays version differences, and provides per-plugin and bulk update commands. Silent checking starts when the settings page is opened.

Changes

Plugin update workflow

Layer / File(s) Summary
Plugin update state and action
Flow.Launcher/ViewModel/PluginViewModel.cs, Flow.Launcher.Core/Plugin/PluginInstaller.cs
PluginViewModel stores UpdateInfo, exposes update-related properties, raises dependent notifications, and invokes plugin installation for individual updates. The installer now returns whether the update succeeds.
Update detection and settings commands
Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs, Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml, Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml.cs
The settings view model refreshes manifests, compares versions, skips user-modified plugins, tracks update counts, opens bulk update UI, and performs silent checks. The page wires check and update-all buttons.
Per-plugin update controls
Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml
Installed plugin headers show current and new versions and expose an update button when an update is available.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SettingsPanePluginsViewModel
  participant PluginInstaller
  participant PluginViewModel
  participant PluginUpdateWindow
  SettingsPanePluginsViewModel->>PluginInstaller: refresh plugin manifest
  SettingsPanePluginsViewModel->>PluginViewModel: set UpdateInfo
  SettingsPanePluginsViewModel->>PluginUpdateWindow: open plugins with updates
  PluginViewModel->>PluginInstaller: update plugin and check restart
Loading

Possibly related PRs

Suggested reviewers: jjw24

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title clearly summarizes the main change: plugin update support in the Plugins settings tab.
Description check ✅ Passed The description is directly related to the changeset and accurately describes the new plugin update features.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🤖 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 `@Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs`:
- Around line 250-251: Replace the lexicographic comparison in the update check
around PluginModified with a semantic-version comparer that correctly orders
numeric components and prerelease versions. Apply the same comparer consistently
to all plugin version comparisons in PluginInstaller.cs and PluginsManager.cs,
preserving the existing update and modification conditions.

In `@Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml.cs`:
- Line 35: Update the silent update-check path around
CheckForUpdatesSilentlyAsync so failures from its asynchronous manifest I/O are
observed, caught, and logged rather than discarded. Preserve the existing
session guard, and explicitly handle whether that guard is cleared when the
silent check fails so the retry behavior is intentional.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 31639003-6e6b-4776-8338-bdfc6881ede1

📥 Commits

Reviewing files that changed from the base of the PR and between 7a651ce and 08a353e.

📒 Files selected for processing (5)
  • Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml
  • Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs
  • Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml
  • Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml.cs
  • Flow.Launcher/ViewModel/PluginViewModel.cs

Comment on lines +250 to +251
if (string.Compare(currentVersion, newVersion, StringComparison.InvariantCulture) < 0
&& !PublicApi.Instance.PluginModified(vm.PluginPair.Metadata.ID))

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find existing version parsing/comparison conventions before adding a new one.
rg -n -C 3 -g '*.cs' '\b(NuGetVersion|SemanticVersion|Version\.(TryParse|Parse)|CompareTo)\b' .
rg -n -g '*.json' '"[Vv]ersion"\s*:' .

Repository: Flow-Launcher/Flow.Launcher

Length of output: 5858


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## Candidate file outline"
ast-grep outline Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs --view compact || true

echo "## Relevant SettingsPanePluginsViewModel section"
sed -n '220,270p' Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs | cat -n

echo "## Relevant PluginManager version methods"
sed -n '860,900p' Flow.Launcher.Core/Plugin/PluginManager.cs | cat -n
sed -n '1145,1170p' Flow.Launcher.Core/Plugin/PluginManager.cs | cat -n

echo "## All string.Compare usages for version strings"
rg -n -C 2 "string\.Compare.*Version|CompareTo\(.*Version|Version\.CompareTo|CompareTo\(.*Metadata\.Version" Flow.Launcher Flow.Launcher.Core Plugins -g '*.cs'

echo "## NuGet / SemanticVersioning package references"
rg -n -g '*.csproj' -g 'packages.lock.json' -g 'packages.config' 'SemanticVersioning|Versioning|Newtonsoft' .
if [ -f Flow.Launcher.csproj ]; then sed -n '1,220p' Flow.Launcher.csproj; fi

Repository: Flow-Launcher/Flow.Launcher

Length of output: 9922


🏁 Script executed:

#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from distutils.version import StrictVersion

samples = [("1.10.0", "1.9.0"), ("1.9.0", "1.10.0")]
for current, newer in samples:
    print(f"current={current!r} newer={newer!r}")
    print("  string invariant compare sign:", "".join(compart_to_sign(current, newer) for _ in range(1) or [str(__import__('re').match(r'(\d+)\.(\d+)\.(\d+)', current).groups() if False)]))
PY

Repository: Flow-Launcher/Flow.Launcher

Length of output: 595


🌐 Web query:

.NET System.Version.CompareTo numeric component version comparison prerelease documentation

💡 Result:

The.NET System.Version class does not support prerelease strings or metadata [1][2][3]. It is designed exclusively to handle numeric versioning components [1][2]. System.Version.CompareTo operates by comparing the four specific numeric components of a version object in order of decreasing importance: major, minor, build, and revision [4][5]. The comparison logic is as follows: 1. Components are compared sequentially: major vs. major, then minor vs. minor, then build vs. build, and finally revision vs. revision [5][6]. 2. For each component pair, the method returns a positive integer if the current object's component is greater, a negative integer if it is smaller, or continues to the next component if they are equal [5][6]. 3. If all defined components are equal, the method returns 0 [7][4]. 4. Any component that is not specified is treated as undefined (internally often represented as -1), and the official documentation notes that an unknown component is assumed to be older than any known component [4][1]. Because System.Version requires all components to be non-negative integers [1][2], it cannot represent or compare semantic versioning (SemVer) prerelease tags (e.g., "1.0.0-alpha") [3]. Developers requiring support for SemVer should use a dedicated library, such as SemVer (SemVersion), which is specifically built to handle prerelease labels and complex version precedence rules [3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## Plugin version fields/types"
rg -n -C 4 -g '*.cs' 'public .*Version|Version\s*{.*get|class PluginMetadata|class UserPlugin|interface IPlugin' .

echo "## SemanticVersioning usage context"
rg -n -C 3 -g '*.cs' 'NuGetVersion|SemanticVersioning' .

Repository: Flow-Launcher/Flow.Launcher

Length of output: 407


🌐 Web query:

NuGet SemanticVersioning NuGetVersion.TryParse prerelease metadata comparison .NET

💡 Result:

In NuGet, version parsing and comparison for prerelease labels and build metadata follow specific rules implemented in the NuGet.Versioning library [1][2]. Prerelease Labels Prerelease labels (e.g., -alpha, -beta.1) affect version precedence [1]. Comparison Rules: 1. Version Precedence: NuGet follows Semantic Versioning (SemVer) standards, where stable versions are considered higher precedence than prerelease versions [1][2]. 2. Label Comparison: Prerelease components are compared using case-insensitive string comparison [1][2]. This means that 1.0.0-alpha and 1.0.0-Alpha are treated as equal [1][2]. 3. Sorting: When comparing two prerelease versions, NuGet determines precedence by comparing the dot-separated identifiers within the labels [1][3]. If an identifier is numeric, it is compared numerically; otherwise, it is compared lexically [3]. Build Metadata Build metadata (e.g., +20260729, +git.sha1) is identified by the + character [3]. Comparison Rules: 1. Ignored in Comparison: Build metadata has no impact on version precedence, equality, or version ranges [4][5][3]. It is not considered part of the package identity [4][5]. 2. Purpose: It is retained for informational purposes, such as display in user interfaces or diagnostics, but it is effectively ignored during sorting and dependency resolution [4][3]. Implementation Notes - NuGetVersion.TryParse: Use the NuGet.Versioning package for programmatic handling of versions [1][2]. The TryParse method handles the parsing of these components into a NuGetVersion object [6]. - Normalization: When a NuGetVersion is normalized (e.g., via ToNormalizedString), metadata is removed because it does not affect identity or precedence [4][5]. - Legacy Behavior: NuGetVersion supports a 4-segment version (Major.Minor.Patch.Revision) for compatibility with System.Version, in addition to standard SemVer [1][2]. If you are sorting versions, use the VersionComparer class provided by the NuGet.Versioning library to ensure correct logic is applied [1][2][7].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## Plugin version fields/types"
rg -n -C 4 -g '*.cs' 'public string Version|string Version|class PluginMetadata|class UserPlugin|interface IPlugin' .

echo "## SemanticVersioning package usages"
rg -n -C 3 -g '*.cs' 'NuGetVersion|SemanticVersioning|VersionComparer|VersionComparer' .

Repository: Flow-Launcher/Flow.Launcher

Length of output: 11779


Compare plugin versions semantically.

Version is a string here, so line 250 treats 1.10.0 as older than 1.9.0; this can hide valid updates. Prefer a semantic-version comparer that also handles prerelease precedence where appropriate, and apply the same semantics to the other plugin version comparisons in PluginInstaller.cs / PluginsManager.cs.

🤖 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 `@Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs` around
lines 250 - 251, Replace the lexicographic comparison in the update check around
PluginModified with a semantic-version comparer that correctly orders numeric
components and prerelease versions. Apply the same comparer consistently to all
plugin version comparisons in PluginInstaller.cs and PluginsManager.cs,
preserving the existing update and modification conditions.

Comment thread Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml.cs

@cubic-dev-ai cubic-dev-ai Bot left a comment

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.

All reported issues were addressed across 5 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs Outdated
Comment thread Flow.Launcher/ViewModel/PluginViewModel.cs Outdated
puk06 added 2 commits July 29, 2026 22:22
Replace lexicographic string.Compare with SemanticVersioning.Version
to correctly compare version numbers (e.g., 1.9.0 < 1.10.0).
- Return bool from UpdatePluginAndCheckRestartAsync so callers know success
- Clear UpdateInfo only when update actually succeeds (not on cancel/failure)
- Notify parent ViewModel via event to refresh toolbar update count
@puk06

puk06 commented Jul 29, 2026

Copy link
Copy Markdown
Author

I don't think this pull request is the right place to compare versions using Semantic Versioning for the Core component, so if I were to create one, it would be in a separate pull request. I've saved it to my stash, so I can create it right away.

- Wrap CheckForUpdatesCoreAsync in try-catch within CheckForUpdatesSilentlyAsync
- Reset _updatesChecked on failure so the user can retry by re-navigating
- Log exceptions via App.API.LogException instead of silently discarding them
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