Skip to content

feat(updates): surface updates as a titlebar label instead of a modal - #3427

Merged
jeanfbrito merged 26 commits into
masterfrom
chore/update
Aug 5, 2026
Merged

feat(updates): surface updates as a titlebar label instead of a modal#3427
jeanfbrito merged 26 commits into
masterfrom
chore/update

Conversation

@rodrigok

@rodrigok rodrigok commented Jul 28, 2026

Copy link
Copy Markdown
Member

Summary

Replaces the modal that interrupted users when an update was available with a blue "Update" pill in the window chrome. Clicking it opens a compact panel with the version change and the install / skip actions; installing turns the pill into a live percentage, and once the download completes it becomes the button that restarts into the new version.

Stacked on chore/tabs-tweaks-2 (#3424) — please merge that first. Review only the three commits on this branch.

The flow

State Pill Behavior
Update available Update Click opens the panel (announcement, current → new version, Install Update / Skip This Version)
Downloading Updating… 45% Reports progress; the fill doubles as a progress bar. Clicks are no-ops
Downloaded Restart to update Click quits and relaunches into the new version

The pill renders in all three navigation layouts (tab strip, sidebar, titlebar) on both macOS and Windows, and is hidden entirely when no update is available.

The panel closes on an outside click, on Escape, and when its own actions are taken.

Details

  • No more modal. UPDATES_NEW_VERSION_AVAILABLE no longer auto-opens the update dialog. That made UpdateDialog unreachable, so it and its four UPDATE_DIALOG_* actions, their main-process listeners, and the "Downloading Update" dialog helper are removed along with the i18n keys they owned. "Remind Me Later" is gone by design — the pill persists, so deferring is the default.
  • About dialog hands over to the panel. "Check for Updates" closes the About dialog and opens the update panel when a version is found, so the version details and the install action live in exactly one place. Scoped to manual checks — the automatic startup check still just reveals the pill without interrupting. (If a background check resolves while About is open, it reports the version inline instead, matching the existing "No updates are available." treatment.)
  • Panel visibility is store-owned. isUpdatePanelOpen / UPDATES_PANEL_TOGGLED replace local component state so the About dialog can open the panel. The reducer also closes it on install, skip, error, or when the update goes away, so it cannot linger in a stale state.
  • Outside clicks close the panel. Fuselage's useOutsideClick binds mousedown on document, but the workspace content is a <webview> whose clicks never reach the host document — clicking the page left the panel open. A transparent full-viewport backdrop now overlays the webview and catches those clicks, with the panel layered above it. Two side effects worth knowing: clicking the pill while the panel is open closes it via the backdrop rather than the pill's own handler (same outcome, and it avoids an open→close→open double-toggle), and the outside click is swallowed rather than passed through to what is underneath.
  • Progress plumbing. Adds the missing electron-updater download-progress listener plus updateDownloadStatus (idle → downloading → downloaded) and updateDownloadProgress state (transient, not persisted). The quit-and-relaunch logic is extracted into installDownloadedUpdate().
  • Stable width. The percentage sits in its own monospaced, right-aligned element sized for two digits plus the percent sign, with tabular-nums, so the pill does not resize as the number climbs and nudge the surrounding chrome.
  • Skip is isolated. The pill dispatches its own UPDATES_SKIP_REQUESTED rather than reusing the dialog action, so the simulated flow cannot persist a fake skippedUpdateVersion into real settings.
  • Hit-testing fix. The shell overlays a fixed 22px WindowDragBar across the top of the window, which is taller than the 28px title bar — it swallowed clicks on all but the bottom few pixels of the pill. The pill is now positioned so it sits above that drag region.

Simulating the flow

Tools → Simulate Update Flow (requires Developer Mode) walks the entire flow — available → downloading → downloaded — without contacting the update server, and never actually restarts. It is registered before the "updating not allowed/enabled" bail-out so it also works in unpackaged development builds.

i18n

The five keys removed from en are dropped from all 15 locale files that carried them, and the trailing colon is removed from currentVersion / newVersion to match en (each language keeps its own wording and capitalization; French loses its preceding space too). New keys are deliberately not added to the other locales — every locale file is already a partial subset and fallbackLng is 'en', so new strings resolve to English until they come through the LingoHub workflow.

Testing

tsc --noEmit, yarn lint, yarn test (154 suites, 1684 passing) and yarn build all pass. New tests cover the three reducers and fourteen UpdateLabel behaviors — panel contents, install, skip, absence of remind-later, close on outside click / Escape, progress display, fixed-width percentage, and restart.

Not yet verified in a running app; the simulate menu item is the quickest way to eyeball the panel's placement and styling.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Replaced the update dialog with a title-bar update indicator and expandable update panel.
    • Added download progress, install, skip, restart, and dismiss actions.
    • Added localized update availability, progress, and restart messaging.
    • Added a developer-only option to simulate an update.
  • Bug Fixes
    • Improved update status handling and progress resets across download, completion, errors, and skipped updates.
    • Updated localized labels and removed the obsolete “Remind me later” option.

rodrigok and others added 18 commits July 17, 2026 13:34
- Follow the resolved theme for the shell palette when the window is
  transparent (opaque stays dark), via a shared useShellTheme hook, so tab
  text stays legible over a light desktop
- Centralize the tab/divider/hover fill into a single --tab-chrome-fill CSS
  variable that inverts with the palette under transparency
- Match the add button hover to the tab fill when transparency is enabled
- Render each tab's divider as a trailing sibling so one sits before the add
  button automatically; drive divider visibility (leading edge, selected and
  hovered flanks) purely in CSS
- Animate tab hover background and divider opacity
- Show the server address on its own tooltip line, stripped from the title
  when the title already embeds it
- Update tab max-width test to 230px to match the strip metrics

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Hide the divider before the add button when the button is hovered
- Round tab corners and align the add button radius
- Dim idle dividers to 50% opacity

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Update WindowControls/MeatballMenuButton specs for the theme-aware icon
  color (token fallback) instead of hardcoded white
- Wrap the long tab outline declaration to satisfy prettier

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The meatball button is now a Fuselage IconButton (theme-managed), so the
hardcoded color assertion no longer applies. Accessibility and click
behavior remain covered by the other specs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Remove WindowsTitleBar; win32 sidebar now uses TopBar with a window-controls
  trailing slot and left text alignment
- TopBar gains trailingSlot / textAlignment; MeatballMenuButton takes an
  orientation prop
- Update Shell spec: TopBar mock renders its trailing slot; win32 sidebar test
  asserts TopBar + window controls instead of the removed WindowsTitleBar

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Replace the Fuselage WorkspaceContextMenu with a native Electron popup
  (reload, force reload, copy URL, open dev tools, server info, remove, add
  workspace); the main process reads the server from state by url
- Trigger it via SERVER_CONTEXT_MENU_TRIGGERED from a tab or the titlebar
  switcher right-click
- Show accelerators for the actions that have app-level shortcuts (reload,
  open dev tools, add workspace) and isolate Remove in its own section
- Delete the now-unused WorkspaceContextMenu and SideBar/ServerInfoDropdown,
  and drop the server-info props they required from WorkspaceTab/TabBar

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The ⇧⌘S / Ctrl+Shift+S accelerator now renders on whichever layout radio
is the next step of the tabs → sidebar → hidden cycle, so pressing it (or
clicking that item) advances the cycle one place. Previously the shortcut
was pinned to the Sidebar radio, which read as "select Sidebar" and made
clicking that item cycle unexpectedly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The unread dot (badge === '•') was gated behind the vertical orientation,
so it never appeared in the horizontal tabs layout. Render it in both
orientations (still suppressed when a numeric mention count is shown).

Also unifies badge styling: UnreadDot now extends TabBadge, TabBadge gets a
white foreground and a subtle outline for contrast, and the floated badge
offset and the titlebar switcher notification color are adjusted to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replaces the theme-appearance Select dropdown with a radio group (Auto /
Light / Dark), mirroring the adjacent Navigation layout setting for a
consistent look in Settings → General.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8fcba97f-988d-47e6-9e22-bb7621531332

📥 Commits

Reviewing files that changed from the base of the PR and between 1483ac3 and 89fbcca.

📒 Files selected for processing (1)
  • src/updates/main.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/updates/main.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout. (4)
  • GitHub Check: build (windows-latest, windows)
  • GitHub Check: build (ubuntu-latest, linux)
  • GitHub Check: check (ubuntu-latest)
  • GitHub Check: check (windows-latest)

Walkthrough

This PR replaces the modal update dialog with a titlebar update label. It adds Redux download state, progress tracking, installation and skip flows, simulated updates, platform-specific placement, legacy-flow removal, and updated translations.

Changes

Titlebar update flow

Layer / File(s) Summary
Update state contracts and Redux slices
src/updates/actions.ts, src/updates/common.ts, src/updates/reducers.ts, src/store/rootReducer.ts, src/updates/reducers/__tests__/*
Adds update lifecycle actions, download status/progress reducers, panel visibility state, Redux slices, and reducer coverage.
Update runtime orchestration and simulation
src/updates/main.ts, src/ui/main/menuBar.ts, src/ui/main/dialogs.*
Connects titlebar download, progress, installation, skipping, error handling, developer simulation, and skipped-update messaging.
Titlebar label UI and modal removal
src/ui/components/TopBar/UpdateLabel.*, src/ui/components/Shell/*, src/ui/components/AboutDialog/index.tsx, src/ui/components/UpdateDialog/*, src/ui/reducers/openDialog.ts, src/ui/actions.ts, src/ui/reducers/__tests__/stateGroups.spec.ts, src/ui/components/TabBar/styles.tsx
Adds the interactive update label, integrates it into platform-specific bars, updates AboutDialog feedback, removes legacy modal handling, and adjusts vertical spacing.
Update interface localization
src/i18n/*.i18n.json
Updates localized update-dialog strings and adds English labels for update availability, simulation, and titlebar progress states.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant HelpMenu
  participant UpdateLabel
  participant setupUpdateLabelFlow
  participant ReduxStore
  participant electronUpdater
  HelpMenu->>setupUpdateLabelFlow: dispatch UPDATES_SIMULATION_REQUESTED
  UpdateLabel->>setupUpdateLabelFlow: dispatch UPDATES_DOWNLOAD_REQUESTED
  setupUpdateLabelFlow->>electronUpdater: start update download
  electronUpdater->>ReduxStore: dispatch download progress
  ReduxStore->>UpdateLabel: render progress and status
  UpdateLabel->>setupUpdateLabelFlow: dispatch UPDATES_INSTALL_REQUESTED
  setupUpdateLabelFlow->>electronUpdater: install downloaded update
Loading

Possibly related PRs

Suggested labels: type: feature

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes replacing the update modal with a titlebar label, which is the pull request's primary change.
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.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • TWEAKS-2: Request failed with status code 401

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.

@rodrigok
rodrigok marked this pull request as draft July 28, 2026 16:47

@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

🧹 Nitpick comments (1)
src/updates/main.ts (1)

425-454: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the unreachable legacy modal fallback.

autoUpdater.autoDownload is set to false, and downloadUpdate() is only called from UPDATES_DOWNLOAD_REQUESTED, which sets isLabelInitiatedDownload = true first. The update-downloaded listener will always take the early return, leaving the askUpdateInstall/warnAboutInstallUpdateLater branch and imports unreachable; remove this dead code to match the legacy-modal cleanup intent.

🤖 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 `@src/updates/main.ts` around lines 425 - 454, Remove the unreachable legacy
modal fallback from the autoUpdater “update-downloaded” listener: after
dispatching UPDATES_UPDATE_DOWNLOADED, reset isLabelInitiatedDownload and return
without calling askUpdateInstall or warnAboutInstallUpdateLater. Remove any
imports or related references used only by that deleted branch, while preserving
the installDownloadedUpdate error handling.
🤖 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 `@src/ui/components/TopBar/UpdateLabel.tsx`:
- Around line 88-102: Update the Percentage styled span’s min-width from 3ch to
4ch so the label reserves space for the full “100%” value without expanding
during download.

In `@src/updates/main.ts`:
- Around line 236-247: Update dispatchUpdateError to dispatch
UPDATES_ERROR_THROWN for all rejected values, not only Error instances. Preserve
Error message, stack, and name fields, while normalizing non-Error values into a
user-visible message and suitable fallback metadata so the reducers can return
the titlebar to idle.

---

Nitpick comments:
In `@src/updates/main.ts`:
- Around line 425-454: Remove the unreachable legacy modal fallback from the
autoUpdater “update-downloaded” listener: after dispatching
UPDATES_UPDATE_DOWNLOADED, reset isLabelInitiatedDownload and return without
calling askUpdateInstall or warnAboutInstallUpdateLater. Remove any imports or
related references used only by that deleted branch, while preserving the
installDownloadedUpdate error handling.
🪄 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: a972cb1f-7692-41ee-9497-ca1aea245286

📥 Commits

Reviewing files that changed from the base of the PR and between b6b6bba and 480cf6b.

📒 Files selected for processing (35)
  • src/i18n/de-DE.i18n.json
  • src/i18n/en.i18n.json
  • src/i18n/es.i18n.json
  • src/i18n/fi.i18n.json
  • src/i18n/fr.i18n.json
  • src/i18n/hu.i18n.json
  • src/i18n/ja.i18n.json
  • src/i18n/no.i18n.json
  • src/i18n/pl.i18n.json
  • src/i18n/pt-BR.i18n.json
  • src/i18n/ru.i18n.json
  • src/i18n/sv.i18n.json
  • src/i18n/tr-TR.i18n.json
  • src/i18n/uk-UA.i18n.json
  • src/i18n/zh-CN.i18n.json
  • src/i18n/zh-TW.i18n.json
  • src/store/rootReducer.ts
  • src/ui/actions.ts
  • src/ui/components/AboutDialog/index.tsx
  • src/ui/components/Shell/index.spec.tsx
  • src/ui/components/Shell/index.tsx
  • src/ui/components/TopBar/UpdateLabel.spec.tsx
  • src/ui/components/TopBar/UpdateLabel.tsx
  • src/ui/components/UpdateDialog/index.spec.tsx
  • src/ui/components/UpdateDialog/index.tsx
  • src/ui/main/dialogs.spec.ts
  • src/ui/main/dialogs.ts
  • src/ui/main/menuBar.ts
  • src/ui/reducers/__tests__/stateGroups.spec.ts
  • src/ui/reducers/openDialog.ts
  • src/updates/actions.ts
  • src/updates/common.ts
  • src/updates/main.ts
  • src/updates/reducers.ts
  • src/updates/reducers/__tests__/updates.spec.ts
💤 Files with no reviewable changes (6)
  • src/ui/components/UpdateDialog/index.spec.tsx
  • src/ui/components/UpdateDialog/index.tsx
  • src/ui/components/Shell/index.spec.tsx
  • src/ui/reducers/openDialog.ts
  • src/ui/actions.ts
  • src/ui/main/dialogs.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use TypeScript for new code unless explicitly told otherwise.
Use Fuselage components from @rocket.chat/fuselage for UI work unless the design requires something Fuselage does not provide.
Check Theme.d.ts for valid color tokens before using Fuselage colors.
Verify library props, APIs, and tokens against official docs or local .d.ts files instead of assuming.
Use React functional components with hooks.
Redux actions follow FSA shape.
Use camelCase for file names and PascalCase for components.
Prefer clear names over unnecessary comments.
Prefer editing existing files over creating new abstractions unless the new abstraction removes real complexity or matches an existing pattern.

**/*.{ts,tsx}: Use TypeScript for all new code unless explicitly told otherwise.
Use Fuselage components for all UI work; create custom components only when Fuselage lacks the required functionality.
Import Fuselage components from @rocket.chat/fuselage.
Use only valid color tokens documented by Theme.d.ts.
Use optional chaining with fallbacks for platform-specific APIs, especially Linux-only process APIs such as process.getuid(), getgid(), geteuid(), and getegid().
Use TypeScript strict mode.
Redux actions must follow the Flux Standard Action pattern.
Use camelCase for file names and PascalCase for component names.
Avoid unnecessary comments; prefer self-documenting code through clear naming.
Do not commit or push without explicit user permission.
Verify library APIs, props, tokens, and types against official documentation and .d.ts files instead of assuming they are valid.

Files:

  • src/updates/common.ts
  • src/ui/components/AboutDialog/index.tsx
  • src/ui/components/Shell/index.tsx
  • src/ui/reducers/__tests__/stateGroups.spec.ts
  • src/updates/reducers/__tests__/updates.spec.ts
  • src/ui/components/TopBar/UpdateLabel.spec.tsx
  • src/updates/reducers.ts
  • src/updates/actions.ts
  • src/ui/components/TopBar/UpdateLabel.tsx
  • src/ui/main/menuBar.ts
  • src/ui/main/dialogs.spec.ts
  • src/updates/main.ts
  • src/store/rootReducer.ts
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use React functional components with hooks.

Files:

  • src/ui/components/AboutDialog/index.tsx
  • src/ui/components/Shell/index.tsx
  • src/ui/components/TopBar/UpdateLabel.spec.tsx
  • src/ui/components/TopBar/UpdateLabel.tsx
**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Renderer specs use *.spec.ts / *.spec.tsx.

Files:

  • src/ui/reducers/__tests__/stateGroups.spec.ts
  • src/updates/reducers/__tests__/updates.spec.ts
  • src/ui/components/TopBar/UpdateLabel.spec.tsx
  • src/ui/main/dialogs.spec.ts
**/*.spec.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use *.spec.ts for renderer process tests.

Files:

  • src/ui/reducers/__tests__/stateGroups.spec.ts
  • src/updates/reducers/__tests__/updates.spec.ts
  • src/ui/main/dialogs.spec.ts
src/**/*.{spec.ts,spec.tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Renderer test files should be placed in nested module paths such as src/<module>/<subdir>/*.spec.ts(x) so Jest discovers them.

Files:

  • src/ui/reducers/__tests__/stateGroups.spec.ts
  • src/updates/reducers/__tests__/updates.spec.ts
  • src/ui/components/TopBar/UpdateLabel.spec.tsx
  • src/ui/main/dialogs.spec.ts
src/*/*/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Renderer specs must live in a Jest-matched nested path, such as src/<module>/<subdir>/*.spec.ts(x); flat src/<module>/*.spec.ts files are not discovered by the current testMatch.

Files:

  • src/ui/main/dialogs.spec.ts
🧠 Learnings (3)
📚 Learning: 2026-06-26T18:14:15.295Z
Learnt from: jeanfbrito
Repo: RocketChat/Rocket.Chat.Electron PR: 3358
File: src/i18n/it-IT.i18n.json:39-42
Timestamp: 2026-06-26T18:14:15.295Z
Learning: In the i18n JSON files, the translation key `minimizeOnClose.disabledHint` is intentionally displayed when `isTrayIconEnabled` is true and the minimize-on-close toggle is disabled. The hint text should therefore instruct the user to disable the tray icon to make the setting available. During reviews, don’t “correct” this translation for seeming mismatches with the toggle state—first confirm it matches the component’s intended behavior; only update the wording if the underlying product logic/UX requirement changes.

Applied to files:

  • src/i18n/es.i18n.json
  • src/i18n/no.i18n.json
  • src/i18n/hu.i18n.json
  • src/i18n/pt-BR.i18n.json
  • src/i18n/uk-UA.i18n.json
  • src/i18n/ru.i18n.json
  • src/i18n/fr.i18n.json
  • src/i18n/tr-TR.i18n.json
  • src/i18n/ja.i18n.json
  • src/i18n/sv.i18n.json
  • src/i18n/de-DE.i18n.json
  • src/i18n/fi.i18n.json
  • src/i18n/pl.i18n.json
  • src/i18n/zh-TW.i18n.json
  • src/i18n/en.i18n.json
  • src/i18n/zh-CN.i18n.json
📚 Learning: 2026-05-19T20:49:24.859Z
Learnt from: nazabucciarelli
Repo: RocketChat/Rocket.Chat.Electron PR: 3329
File: src/ui/reducers/e2ePdfPreviewSizeLimit.ts:14-16
Timestamp: 2026-05-19T20:49:24.859Z
Learning: In Rocket.Chat.Electron’s reducer files under src/ui/reducers/, reducers should not re-implement validation for action payloads. Assume the caller (UI component or dispatch site) has already validated the action payload and type/shape; reducers should trust the payload and update state directly. If validation is needed, add it at the dispatch site/caller rather than inside the reducer.

Applied to files:

  • src/ui/reducers/__tests__/stateGroups.spec.ts
📚 Learning: 2026-05-19T20:49:24.859Z
Learnt from: nazabucciarelli
Repo: RocketChat/Rocket.Chat.Electron PR: 3329
File: src/ui/reducers/e2ePdfPreviewSizeLimit.ts:14-16
Timestamp: 2026-05-19T20:49:24.859Z
Learning: In the Rocket.Chat.Electron UI reducers under src/ui/reducers/, do not add/repeat input validation for action payloads inside reducers. Follow the existing codebase pattern: validate the action payload in the caller (e.g., the UI component or dispatch site) before dispatching. Reducers should trust the incoming payload and apply it directly to state. If adding/updating a reducer, ensure the corresponding caller performs the necessary validation (e.g., check numeric constraints like !isNaN(value) && value > 0 before dispatching the action).

Applied to files:

  • src/ui/reducers/__tests__/stateGroups.spec.ts
🔇 Additional comments (32)
src/updates/actions.ts (1)

13-22: LGTM!

Also applies to: 33-38

src/updates/main.ts (4)

6-30: LGTM!


168-234: LGTM!


254-309: LGTM!

Also applies to: 358-361


501-501: LGTM!

src/ui/main/menuBar.ts (1)

12-15: LGTM!

Also applies to: 828-842

src/ui/components/TopBar/UpdateLabel.spec.tsx (1)

1-195: LGTM!

src/i18n/hu.i18n.json (1)

82-89: LGTM!

src/i18n/ja.i18n.json (1)

52-59: LGTM!

src/i18n/no.i18n.json (1)

82-89: LGTM!

src/i18n/pl.i18n.json (1)

59-66: LGTM!

src/i18n/pt-BR.i18n.json (1)

82-89: LGTM!

src/updates/common.ts (1)

31-36: LGTM!

src/updates/reducers.ts (1)

11-21: LGTM!

Also applies to: 229-284

src/store/rootReducer.ts (1)

68-69: LGTM!

Also applies to: 111-112

src/updates/reducers/__tests__/updates.spec.ts (1)

8-14: LGTM!

Also applies to: 26-27, 369-442

src/i18n/ru.i18n.json (1)

68-74: LGTM!

src/i18n/sv.i18n.json (1)

82-89: LGTM!

src/i18n/tr-TR.i18n.json (1)

52-59: LGTM!

src/i18n/uk-UA.i18n.json (1)

52-59: LGTM!

src/i18n/zh-CN.i18n.json (1)

53-60: LGTM!

src/i18n/zh-TW.i18n.json (1)

53-60: LGTM!

src/ui/components/TopBar/UpdateLabel.tsx (1)

1-81: LGTM!

Also applies to: 104-254

src/ui/components/Shell/index.tsx (1)

25-25: LGTM!

Also applies to: 77-100, 113-118

src/ui/components/AboutDialog/index.tsx (1)

149-162: LGTM!

src/ui/main/dialogs.spec.ts (1)

4-19: LGTM!

Also applies to: 330-346

src/ui/reducers/__tests__/stateGroups.spec.ts (1)

326-329: LGTM!

src/i18n/en.i18n.json (1)

26-26: LGTM!

Also applies to: 84-89, 415-415, 529-535

src/i18n/de-DE.i18n.json (1)

69-70: LGTM!

src/i18n/es.i18n.json (1)

76-77: LGTM!

src/i18n/fi.i18n.json (1)

76-77: LGTM!

src/i18n/fr.i18n.json (1)

76-77: LGTM!

Comment thread src/ui/components/TopBar/UpdateLabel.tsx
Comment thread src/updates/main.ts
Comment on lines +236 to +247
const dispatchUpdateError = (error: unknown): void => {
if (error instanceof Error) {
dispatch({
type: UPDATES_ERROR_THROWN,
payload: {
message: error.message,
stack: error.stack,
name: error.name,
},
});
}
};

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.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Non-Error rejections are silently dropped, leaving the titlebar stuck "downloading".

dispatchUpdateError only dispatches UPDATES_ERROR_THROWN when error instanceof Error. If a rejection isn't an Error instance, nothing is dispatched, and per the updateDownloadStatus/updateDownloadProgress reducers the label has no other way back to 'idle' — it stays stuck reporting "downloading" with no error surfaced to the user.

🛡️ Proposed fix to normalize non-Error rejections
 const dispatchUpdateError = (error: unknown): void => {
-  if (error instanceof Error) {
-    dispatch({
-      type: UPDATES_ERROR_THROWN,
-      payload: {
-        message: error.message,
-        stack: error.stack,
-        name: error.name,
-      },
-    });
-  }
+  const normalized =
+    error instanceof Error ? error : new Error(String(error));
+  dispatch({
+    type: UPDATES_ERROR_THROWN,
+    payload: {
+      message: normalized.message,
+      stack: normalized.stack,
+      name: normalized.name,
+    },
+  });
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const dispatchUpdateError = (error: unknown): void => {
if (error instanceof Error) {
dispatch({
type: UPDATES_ERROR_THROWN,
payload: {
message: error.message,
stack: error.stack,
name: error.name,
},
});
}
};
const dispatchUpdateError = (error: unknown): void => {
const normalized =
error instanceof Error ? error : new Error(String(error));
dispatch({
type: UPDATES_ERROR_THROWN,
payload: {
message: normalized.message,
stack: normalized.stack,
name: normalized.name,
},
});
};
🤖 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 `@src/updates/main.ts` around lines 236 - 247, Update dispatchUpdateError to
dispatch UPDATES_ERROR_THROWN for all rejected values, not only Error instances.
Preserve Error message, stack, and name fields, while normalizing non-Error
values into a user-visible message and suitable fallback metadata so the
reducers can return the titlebar to idle.

@rodrigok rodrigok closed this Jul 28, 2026
@rodrigok rodrigok reopened this Jul 28, 2026
rodrigok and others added 4 commits July 28, 2026 14:25
Clicking the meatball button while holding the shortcut modifier left the tab
numbers stuck on screen until the modifier was pressed again: the native menu
grabs input, so the `keyup` never reached the renderer. The window `blur` and
`visibilitychange` events now clear them, with a `mousemove` resync from the
event's modifier flag as a backstop for platforms where the popup does not
blur the web contents.

Presses and releases are still tracked by key name, because Chromium reports
metaKey/ctrlKey as false on the modifier's own keydown — deriving visibility
purely from that flag would keep the numbers hidden until the pointer moved.
Other keys resync from the flag so combinations such as ⌘1 keep them visible.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
An available update now appears as a blue pill in the window chrome rather
than interrupting the user with a modal dialog. Clicking it opens a panel
with the version change and the install / skip actions; installing turns the
pill into a live percentage, and once the download finishes it becomes the
button that restarts into the new version.

The pill is rendered in every navigation layout (tab strip, sidebar and
titlebar, on both macOS and Windows). The percentage lives in its own
monospaced, right-aligned element sized for two digits plus the percent sign
so the pill keeps a constant width as the number climbs.

Adds the missing electron-updater `download-progress` listener along with
`updateDownloadStatus` (idle → downloading → downloaded) and
`updateDownloadProgress` state, and extracts the quit-and-relaunch logic into
`installDownloadedUpdate()`.

Removes the now-unreachable legacy modal path: the `update` dialog is no
longer auto-opened on UPDATES_NEW_VERSION_AVAILABLE, and the UpdateDialog
component, its four UPDATE_DIALOG_* actions and their main-process listeners,
and the "Downloading Update" dialog helper are all deleted. The About dialog
reported nothing when a manual check found an update (the modal used to take
over), so it now reports the version inline.

Tools → Simulate Update Flow (developer mode) walks the whole flow without
contacting the update server and never restarts, so the states can be
exercised locally. It is registered before the "updating not allowed" bail-out
so it also works in unpackaged development builds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drops the five keys removed from en, which were dead in every locale:
dialog.update.title, dialog.update.remindLater and the whole
dialog.updateDownloading block.

Also removes the trailing colon from dialog.update.currentVersion and
dialog.update.newVersion to match en, keeping each language's own wording and
capitalization (French loses its preceding space along with the colon, per
French typography).

Keys added in en are intentionally left out: every locale file is already a
partial subset and fallbackLng is 'en', so new strings resolve to English
until they come through the translation workflow.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…outside click

"Check for Updates" in the About dialog now closes that dialog and opens the
titlebar update panel when a version is found, so the version details and the
install action live in one place. This is scoped to manual checks — the
automatic startup check still just reveals the pill without interrupting.

Panel visibility moves from local component state into the store
(isUpdatePanelOpen / UPDATES_PANEL_TOGGLED) so the About dialog can open it.
The reducer also closes the panel on install, skip, error, or when the update
goes away, so it cannot linger in a stale state.

Clicking outside the panel now closes it. The previous useOutsideClick binds
mousedown on document, but the workspace content is a <webview> whose clicks
never reach the host document, so clicking the page left the panel open. A
transparent full-viewport backdrop overlays the webview and catches those
clicks, with the panel layered above it. Escape closes the panel too.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown

On Windows the update pill moves from the trailing slot into the leading one,
so the title bar reads meatball then pill and only the window controls trail.
macOS keeps the pill trailing.

The panel follows the pill: it anchors to bottom-start on Windows and stays
bottom-end elsewhere, so it opens inward from whichever edge the pill sits on
instead of off the side of the window.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@rodrigok
rodrigok marked this pull request as ready for review July 28, 2026 18:43

@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: 1

🤖 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 `@src/ui/components/TopBar/UpdateLabel.tsx`:
- Line 1: Update UpdateLabel to select and render updateError for
UPDATES_ERROR_THROWN, ensuring titlebar download failures display an error state
instead of resetting to or appearing as “available”; adjust updateDownloadStatus
and updateDownloadProgress so the stored error state is preserved, and add
coverage for this failure path in UpdateLabel.spec.tsx.
🪄 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: a4025772-6c3c-41fd-9e92-1e6fa1c137eb

📥 Commits

Reviewing files that changed from the base of the PR and between 480cf6b and c311507.

📒 Files selected for processing (35)
  • src/i18n/de-DE.i18n.json
  • src/i18n/en.i18n.json
  • src/i18n/es.i18n.json
  • src/i18n/fi.i18n.json
  • src/i18n/fr.i18n.json
  • src/i18n/hu.i18n.json
  • src/i18n/ja.i18n.json
  • src/i18n/no.i18n.json
  • src/i18n/pl.i18n.json
  • src/i18n/pt-BR.i18n.json
  • src/i18n/ru.i18n.json
  • src/i18n/sv.i18n.json
  • src/i18n/tr-TR.i18n.json
  • src/i18n/uk-UA.i18n.json
  • src/i18n/zh-CN.i18n.json
  • src/i18n/zh-TW.i18n.json
  • src/store/rootReducer.ts
  • src/ui/actions.ts
  • src/ui/components/AboutDialog/index.tsx
  • src/ui/components/Shell/index.spec.tsx
  • src/ui/components/Shell/index.tsx
  • src/ui/components/TopBar/UpdateLabel.spec.tsx
  • src/ui/components/TopBar/UpdateLabel.tsx
  • src/ui/components/UpdateDialog/index.spec.tsx
  • src/ui/components/UpdateDialog/index.tsx
  • src/ui/main/dialogs.spec.ts
  • src/ui/main/dialogs.ts
  • src/ui/main/menuBar.ts
  • src/ui/reducers/__tests__/stateGroups.spec.ts
  • src/ui/reducers/openDialog.ts
  • src/updates/actions.ts
  • src/updates/common.ts
  • src/updates/main.ts
  • src/updates/reducers.ts
  • src/updates/reducers/__tests__/updates.spec.ts
💤 Files with no reviewable changes (6)
  • src/ui/components/UpdateDialog/index.spec.tsx
  • src/ui/components/Shell/index.spec.tsx
  • src/ui/components/UpdateDialog/index.tsx
  • src/ui/main/dialogs.ts
  • src/ui/actions.ts
  • src/ui/reducers/openDialog.ts
🚧 Files skipped from review as they are similar to previous changes (22)
  • src/updates/common.ts
  • src/ui/reducers/tests/stateGroups.spec.ts
  • src/i18n/pt-BR.i18n.json
  • src/i18n/de-DE.i18n.json
  • src/i18n/uk-UA.i18n.json
  • src/i18n/sv.i18n.json
  • src/i18n/fi.i18n.json
  • src/i18n/tr-TR.i18n.json
  • src/i18n/fr.i18n.json
  • src/i18n/zh-TW.i18n.json
  • src/i18n/es.i18n.json
  • src/updates/actions.ts
  • src/i18n/zh-CN.i18n.json
  • src/i18n/hu.i18n.json
  • src/i18n/en.i18n.json
  • src/i18n/ja.i18n.json
  • src/i18n/ru.i18n.json
  • src/ui/main/dialogs.spec.ts
  • src/updates/reducers/tests/updates.spec.ts
  • src/ui/main/menuBar.ts
  • src/i18n/pl.i18n.json
  • src/updates/main.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (6)
  • GitHub Check: check (ubuntu-latest)
  • GitHub Check: check (macos-latest)
  • GitHub Check: check (windows-latest)
  • GitHub Check: build (windows-latest, windows)
  • GitHub Check: build (macos-latest, mac)
  • GitHub Check: build (ubuntu-latest, linux)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use TypeScript for new code unless explicitly told otherwise.
Use Fuselage components from @rocket.chat/fuselage for UI work unless the design requires something Fuselage does not provide.
Check Theme.d.ts for valid color tokens before using Fuselage colors.
Verify library props, APIs, and tokens against official docs or local .d.ts files instead of assuming.
Use React functional components with hooks.
Redux actions follow FSA shape.
Use camelCase for file names and PascalCase for components.
Prefer clear names over unnecessary comments.
Prefer editing existing files over creating new abstractions unless the new abstraction removes real complexity or matches an existing pattern.

**/*.{ts,tsx}: Use TypeScript for all new code unless explicitly told otherwise.
Use Fuselage components for all UI work; create custom components only when Fuselage lacks the required functionality.
Import Fuselage components from @rocket.chat/fuselage.
Use only valid color tokens documented by Theme.d.ts.
Use optional chaining with fallbacks for platform-specific APIs, especially Linux-only process APIs such as process.getuid(), getgid(), geteuid(), and getegid().
Use TypeScript strict mode.
Redux actions must follow the Flux Standard Action pattern.
Use camelCase for file names and PascalCase for component names.
Avoid unnecessary comments; prefer self-documenting code through clear naming.
Do not commit or push without explicit user permission.
Verify library APIs, props, tokens, and types against official documentation and .d.ts files instead of assuming they are valid.

Files:

  • src/store/rootReducer.ts
  • src/ui/components/AboutDialog/index.tsx
  • src/ui/components/Shell/index.tsx
  • src/ui/components/TopBar/UpdateLabel.spec.tsx
  • src/updates/reducers.ts
  • src/ui/components/TopBar/UpdateLabel.tsx
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use React functional components with hooks.

Files:

  • src/ui/components/AboutDialog/index.tsx
  • src/ui/components/Shell/index.tsx
  • src/ui/components/TopBar/UpdateLabel.spec.tsx
  • src/ui/components/TopBar/UpdateLabel.tsx
**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Renderer specs use *.spec.ts / *.spec.tsx.

Files:

  • src/ui/components/TopBar/UpdateLabel.spec.tsx
src/**/*.{spec.ts,spec.tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Renderer test files should be placed in nested module paths such as src/<module>/<subdir>/*.spec.ts(x) so Jest discovers them.

Files:

  • src/ui/components/TopBar/UpdateLabel.spec.tsx
🧠 Learnings (1)
📚 Learning: 2026-06-26T18:14:15.295Z
Learnt from: jeanfbrito
Repo: RocketChat/Rocket.Chat.Electron PR: 3358
File: src/i18n/it-IT.i18n.json:39-42
Timestamp: 2026-06-26T18:14:15.295Z
Learning: In the i18n JSON files, the translation key `minimizeOnClose.disabledHint` is intentionally displayed when `isTrayIconEnabled` is true and the minimize-on-close toggle is disabled. The hint text should therefore instruct the user to disable the tray icon to make the setting available. During reviews, don’t “correct” this translation for seeming mismatches with the toggle state—first confirm it matches the component’s intended behavior; only update the wording if the underlying product logic/UX requirement changes.

Applied to files:

  • src/i18n/no.i18n.json
🔇 Additional comments (10)
src/updates/reducers.ts (1)

11-23: LGTM!

Also applies to: 231-316

src/store/rootReducer.ts (1)

64-70: LGTM!

Also applies to: 98-98, 113-114

src/ui/components/TopBar/UpdateLabel.tsx (3)

49-49: 📐 Maintainability & Code Quality

Verify these CSS custom properties are documented Fuselage tokens.

The gradient/colors reference raw --rcx-color-* variables with hex fallbacks rather than Fuselage's documented color tokens/props. Please confirm these variable names exist and resolve to the intended theme colors (they aren't type-checked, so a typo or renamed token would silently fall back to the hardcoded hex).

As per coding guidelines: "Use only valid color tokens documented by Theme.d.ts."

Also applies to: 60-79

Source: Coding guidelines


124-222: LGTM!


224-322: LGTM!

src/ui/components/TopBar/UpdateLabel.spec.tsx (1)

1-237: LGTM!

src/ui/components/Shell/index.tsx (1)

25-25: LGTM!

Also applies to: 74-117, 155-155

src/ui/components/AboutDialog/index.tsx (2)

178-204: LGTM!


152-166: 🎯 Functional Correctness

dialog.about.updateAvailable is defined in the English strings.

src/i18n/no.i18n.json (1)

82-89: LGTM!

@@ -0,0 +1,324 @@
import styled from '@emotion/styled';

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.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg '(^src/ui/components/TopBar/(UpdateLabel\.(tsx|spec\.tsx|ts)|.*TopBar.*)$|src/updates/main.ts|src/ui/components/AboutDialog/index.tsx|.*update.*|redux|reducers|action)'

echo
echo "== UpdateLabel outline =="
ast-grep outline src/ui/components/TopBar/UpdateLabel.tsx --view compact || true

echo
echo "== UpdateLabel relevant imports/section =="
sed -n '1,260p' src/ui/components/TopBar/UpdateLabel.tsx

echo
echo "== UpdateLabel spec summary =="
wc -l src/ui/components/TopBar/UpdateLabel.spec.tsx
sed -n '1,320p' src/ui/components/TopBar/UpdateLabel.spec.tsx

echo
echo "== Search updateDownloadStatus and updateError =="
rg -n "updateDownloadStatus|UPDATES_ERROR_THROWN|updateError|newUpdateVersion|currentVersion|download.*status|download.*progress" src -g '*.ts' -g '*.tsx' | head -300

Repository: RocketChat/Rocket.Chat.Electron

Length of output: 29996


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== updates reducers relevant section =="
sed -n '1,220p' src/updates/reducers.ts
sed -n '220,340p' src/updates/reducers.ts

echo
echo "== updates main relevant error handling section =="
sed -n '220,250p' src/updates/main.ts
sed -n '420,485p' src/updates/main.ts
sed -n '485,510p' src/updates/main.ts

echo
echo "== AboutDialog updateError handling section =="
sed -n '80,180p' src/ui/components/AboutDialog/index.tsx

echo
echo "== update action definitions/types =="
sed -n '1,80p' src/updates/actions.ts
sed -n '1,50p' src/updates/reducers.ts

echo
echo "== structural verifier for UpdateLabel selectors and updateDownloadStatus reducer =="
python3 - <<'PY'
from pathlib import Path
import re

update_label = Path('src/ui/components/TopBar/UpdateLabel.tsx').read_text()
updates_reducer = Path('src/updates/reducers.ts').read_text()

selectors = re.findall(r'({\w+:RootState}\)\) =>\s*(\w+))', update_label)
names = [s[1] for s in selectors]
print("UpdateLabel selectors:", names)
print("selects updateError:", "updateError" in names)
print("updateDownloadStatus occurrences in UpdateLabel:", update_label.count("updateDownloadStatus"))

status_matches = re.findall(r'case\s+UPDATES_ERROR_THROWN:;?\s*return\s+([\'"])(idle|downloading|downloaded|failed|error|erred)\1|case\s+UPDATES_ERROR_THROWN:\s*return\s+([\'"])(idle|downloading|downloaded|failed|error|erred)\3', updates_reducer)
for m in status_matches:
    print("UPDATES_ERROR_THROWN status return:", next(filter(None, m)))

print("UpdateLabel mentions updateError:", bool(re.search(r'updateError', update_label)))
print("UpdateLabel spec mentions updateError:", bool(re.search(r'updateError', Path('src/ui/components/TopBar/UpdateLabel.spec.tsx').read_text())))
PY

Repository: RocketChat/Rocket.Chat.Electron

Length of output: 19063


Surface download failures on the titlebar update pill. UPDATES_ERROR_THROWN stores the error, but updateDownloadStatus and updateDownloadProgress reset to idle, and UpdateLabel does not select updateError, so a failed titlebar-initiated download falls back to “available”. Also cover this path in src/ui/components/TopBar/UpdateLabel.spec.tsx.

🤖 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 `@src/ui/components/TopBar/UpdateLabel.tsx` at line 1, Update UpdateLabel to
select and render updateError for UPDATES_ERROR_THROWN, ensuring titlebar
download failures display an error state instead of resetting to or appearing as
“available”; adjust updateDownloadStatus and updateDownloadProgress so the
stored error state is preserved, and add coverage for this failure path in
UpdateLabel.spec.tsx.

Base automatically changed from chore/tabs-tweaks-2 to master August 3, 2026 17:02
Resolves conflicts with the merged tab/badge work:
- Shell: keep this PR's UpdateLabel in the TabBar/TopBar slots (replacing
  the UpdateDialog modal) and its Windows top-padding adjustment
- TabBar (WorkspaceTab, styles, spec) and ServerSwitcher: take master's
  side — the badge redesign and priority logic from #3434 plus its token
  fix supersede the pre-redesign versions this branch carried

@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.

Caution

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

⚠️ Outside diff range comments (1)
src/ui/components/TabBar/styles.tsx (1)

373-376: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Replace the hard-coded shadow color with a documented theme token.

rgba(0, 0, 0, 0.2) is not a documented Theme.d.ts color token. Use the matching theme token or CSS variable instead.

As per coding guidelines, use only valid color tokens documented by Theme.d.ts.

🤖 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 `@src/ui/components/TabBar/styles.tsx` around lines 373 - 376, Update the
TabBadge styled component to replace the hard-coded rgba box-shadow color with
the matching documented theme color token or CSS variable from Theme.d.ts, while
preserving the existing shadow dimensions and styling.

Source: Coding guidelines

🤖 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.

Outside diff comments:
In `@src/ui/components/TabBar/styles.tsx`:
- Around line 373-376: Update the TabBadge styled component to replace the
hard-coded rgba box-shadow color with the matching documented theme color token
or CSS variable from Theme.d.ts, while preserving the existing shadow dimensions
and styling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fc234b57-0c89-4ae9-8ef4-6d1392c6e31b

📥 Commits

Reviewing files that changed from the base of the PR and between c311507 and 1483ac3.

📒 Files selected for processing (1)
  • src/ui/components/TabBar/styles.tsx
📜 Review details
⏰ Context from checks skipped due to timeout. (5)
  • GitHub Check: build (windows-latest, windows)
  • GitHub Check: build (ubuntu-latest, linux)
  • GitHub Check: check (ubuntu-latest)
  • GitHub Check: check (windows-latest)
  • GitHub Check: Analyze (actions)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use TypeScript for new code unless explicitly told otherwise.
Use Fuselage components from @rocket.chat/fuselage for UI work unless the design requires something Fuselage does not provide.
Check Theme.d.ts for valid color tokens before using Fuselage colors.
Verify library props, APIs, and tokens against official docs or local .d.ts files instead of assuming.
Use React functional components with hooks.
Redux actions follow FSA shape.
Use camelCase for file names and PascalCase for components.
Prefer clear names over unnecessary comments.
Prefer editing existing files over creating new abstractions unless the new abstraction removes real complexity or matches an existing pattern.

**/*.{ts,tsx}: Use TypeScript for all new code unless explicitly told otherwise.
Use Fuselage components for all UI work; create custom components only when Fuselage lacks the required functionality.
Import Fuselage components from @rocket.chat/fuselage.
Use only valid color tokens documented by Theme.d.ts.
Use optional chaining with fallbacks for platform-specific APIs, especially Linux-only process APIs such as process.getuid(), getgid(), geteuid(), and getegid().
Use TypeScript strict mode.
Redux actions must follow the Flux Standard Action pattern.
Use camelCase for file names and PascalCase for component names.
Avoid unnecessary comments; prefer self-documenting code through clear naming.
Do not commit or push without explicit user permission.
Verify library APIs, props, tokens, and types against official documentation and .d.ts files instead of assuming they are valid.

Files:

  • src/ui/components/TabBar/styles.tsx
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use React functional components with hooks.

Files:

  • src/ui/components/TabBar/styles.tsx
🔇 Additional comments (1)
src/ui/components/TabBar/styles.tsx (1)

72-72: LGTM!

Also applies to: 367-372, 378-432

A failed downloadUpdate() left isLabelInitiatedDownload set, so a later
successful download would incorrectly skip the install prompt on the
non-label path.
@jeanfbrito

Copy link
Copy Markdown
Member

Reviewed after resolving the merge conflicts with master (1483ac3). Summary:

Verified correct:

  • UPDATE_SKIPPED clears newUpdateVersion, so the pill disappears after Skip
  • The label is reachable in all four Shell layout/platform combinations (tabs/topbar × win32/other)
  • The simulated flow never persists fake state (skip/install during simulation only unwind it)
  • autoUpdater.autoDownload = false is preserved — the label flow controls downloads explicitly
  • Locales without the new tabBar.update.* keys fall back to English; stale dialog.updateDownloading keys were cleaned from every locale
  • UpdateDialog and its legacy actions were fully removed — no dead references

Fixed in 89fbcca: a failed downloadUpdate() left isLabelInitiatedDownload set, so a later successful download would incorrectly skip the install prompt on the non-label path.

Noted, not changed: a manual update check during an in-flight download momentarily resets updateDownloadStatus to idle until the next progress tick (rare, self-correcting, reducer comment documents the intent); with every download now label-initiated, the legacy askUpdateInstall modal path is effectively unreachable and could be removed in a follow-up.

Validation on the merged branch: tsc --noEmit clean, yarn lint clean, full suite 155 suites / 1695 passed / 2 skipped, yarn build clean.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants