Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fix-imageblock-cached-image-race.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/fuselage-ui-kit': patch
---

Fix race condition in ImageBlock where cached images could trigger load event before event listener was attached, causing images to never render properly in UIKit blocks.
9 changes: 5 additions & 4 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ enableImmutableInstalls: false

nodeLinker: node-modules

plugins:
- path: .yarn/plugins/@yarnpkg/plugin-engines.cjs
spec: "https://raw.githubusercontent.com/devoto13/yarn-plugin-engines/main/bundles/%40yarnpkg/plugin-engines.js"
# Temporarily disabled engines plugin for development
# plugins:
# - path: .yarn/plugins/@yarnpkg/plugin-engines.cjs
# spec: "https://raw.githubusercontent.com/devoto13/yarn-plugin-engines/main/bundles/%40yarnpkg/plugin-engines.js"
Comment on lines +11 to +14
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== .yarnrc.yml =="
sed -n '1,25p' .yarnrc.yml

echo
echo "== package.json files declaring engines =="
while IFS= read -r file; do
  if jq -e '.engines?' "$file" >/dev/null; then
    printf '\n==> %s\n' "$file"
    jq '.engines' "$file"
  fi
done < <(fd '^package\.json$')

Repository: RocketChat/Rocket.Chat

Length of output: 616


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Searching for 'engines' in package.json files =="
find . -name 'package.json' -type f | head -20 | while read -r file; do
  if grep -q '"engines"' "$file" 2>/dev/null; then
    printf '%s:\n' "$file"
    grep -A 3 '"engines"' "$file"
    echo
  fi
done

echo "== Total package.json files in repo =="
find . -name 'package.json' -type f | wc -l

Repository: RocketChat/Rocket.Chat

Length of output: 159


Remove temporary development changes from shared config and enable immutable installs.

Lines 11-14 comment out the engines plugin as a temporary development workaround in the committed .yarnrc.yml, which affects all installs on this branch. Per the project guidelines, temporary development-only changes should not be in shared config—either revert them or isolate them in a separate commit.

Additionally, line 5 sets enableImmutableInstalls: false, which disables reproducible installs. The Yarn configuration should enable immutable installs (enableImmutableInstalls: true) with the Yarn version pinned via Corepack in package.json.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.yarnrc.yml around lines 11 - 14, Uncomment the temporary development change
by restoring the plugins block (the commented "plugins:" entry and its child
path/spec lines that reference `@yarnpkg/plugin-engines`) so the engines plugin is
enabled in shared config, and set enableImmutableInstalls: true (replace the
current enableImmutableInstalls: false) to enforce immutable installs; also
ensure the Yarn version is pinned via Corepack in package.json so immutable
installs are reproducible.


yarnPath: .yarn/releases/yarn-4.12.0.cjs
yarnPath: .yarn/releases/yarn-4.12.0.cjs
14 changes: 8 additions & 6 deletions packages/fuselage-ui-kit/src/blocks/ImageBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,20 @@ const ImageBlock = ({ className, block, surfaceRenderer }: ImageBlockProps): Rea

useEffect(() => {
const img = document.createElement('img');
img.src = block.imageUrl;

// If image is already cached and loaded, update state immediately
if (img.complete) {
setState(fetchImageState(img));
return;
}

// Otherwise, wait for the load event
const handleLoad = () => {
setState(fetchImageState(img));
};

img.addEventListener('load', handleLoad);
img.src = block.imageUrl;

if (img.complete) {
img.removeEventListener('load', handleLoad);
setState(fetchImageState(img));
}

return () => {
img.removeEventListener('load', handleLoad);
Expand Down
1 change: 1 addition & 0 deletions packages/livechat/webpack.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ const config = (_env: any, args: webpack.WebpackOptionsNormalized): webpack.Conf
'process.env.NODE_ENV': JSON.stringify(args.mode === 'production' ? 'production' : 'development'),
}),
new HtmlWebpackPlugin({
template: _('./src/index.ejs'),
title: 'Livechat - Rocket.Chat',
chunks: ['polyfills', 'vendor', 'bundle'],
chunksSortMode: 'manual',
Expand Down