-
Notifications
You must be signed in to change notification settings - Fork 298
feat: integrate Collabora using iframe [WPB-21650] #19813
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR integrates Collabora Online for real-time collaborative document editing via iframe embedding. Users can now edit supported file types (docx, xlsx, pptx, odf) directly within the Wire webapp through a toggle between "Viewing" and "Editing" modes in the file preview modal.
Key Changes:
- Added
FileEditorcomponent that renders Collabora URLs in an iframe with auto-refresh logic before URL expiry - Extended file preview modals with edit mode state management and UI toggle buttons
- Implemented
isFileEditable()utility to determine which file extensions support collaborative editing - Propagated asset IDs (UUIDs) through component hierarchy replacing React
useId()for consistent identification
Reviewed changes
Copilot reviewed 30 out of 31 changed files in this pull request and generated 19 comments.
Show a summary per file
| File | Description |
|---|---|
src/script/components/FileFullscreenModal/FileEditor/FileEditor.tsx |
New component rendering Collabora iframe with URL refresh logic |
src/script/components/FileFullscreenModal/FileEditor/FileEditor.styles.ts |
Styles for the iframe editor (full width/height) |
src/script/components/FileFullscreenModal/FileFullscreenModal.tsx |
Added edit mode state and conditional rendering of FileEditor vs standard preview |
src/script/components/FileFullscreenModal/FileHeader/FileHeader.tsx |
Added Viewing/Editing toggle buttons and updated download logic to fetch fresh presigned URLs |
src/script/components/FileFullscreenModal/FileHeader/FileHeader.styles.ts |
Styles for edit mode toggle button group |
src/script/util/FileTypeUtil.ts |
New isFileEditable() function checking if file extension supports editing |
src/script/util/FileTypeUtil.test.ts |
Comprehensive tests for isFileEditable() covering various edge cases |
src/script/util/getFileTypeFromExtension/getFileTypeFromExtension.ts |
Added 'odf' to document extensions list |
src/script/repositories/cells/CellsRepository.ts |
Extended getNode() to accept flags and options parameters |
src/script/components/MessagesList/Message/ContentMessage/asset/MultipartAssets/FileAssetCard/common/FileAssetOptions/FileAssetOptions.tsx |
Added "Edit" option to file dropdown menu for editable files |
src/script/components/MessagesList/Message/ContentMessage/asset/MultipartAssets/FileAssetCard/common/FileAssetOptions/FileAssetOptions.test.tsx |
Tests verifying edit option behavior with different file types |
src/script/components/MessagesList/Message/ContentMessage/asset/MultipartAssets/FileAssetCard/common/FilePreviewModal/FilePreviewModal.tsx |
Pass through isEditMode prop |
src/script/components/MessagesList/Message/ContentMessage/asset/MultipartAssets/FileAssetCard/FileAssetWithPreview/FileAssetWithPreview.tsx |
Track edit mode state and handle modal open/close with edit flag |
src/script/components/MessagesList/Message/ContentMessage/asset/MultipartAssets/FileAssetCard/FileAssetSmall/FileAssetSmall.tsx |
Track edit mode state and pass through asset ID |
src/script/components/MessagesList/Message/ContentMessage/asset/MultipartAssets/FileAssetCard/FileAssetCard.tsx |
Pass through asset ID prop |
src/script/components/MessagesList/Message/ContentMessage/asset/MultipartAssets/MultipartAssets.tsx |
Pass asset UUID as ID to child components |
src/script/components/MessagesList/Message/ContentMessage/asset/MultipartAssets/ImageAssetCard/* |
Replace useId() with prop-based ID (UUID) |
src/script/components/MessagesList/Message/ContentMessage/asset/MultipartAssets/VideoAssetCard/* |
Replace useId() with prop-based ID (UUID) |
src/script/components/Conversation/ConversationCells/CellsTable/common/CellsFilePreviewModalContext/CellsFilePreviewModalContext.tsx |
Add isEditMode state and parameter to handleOpenFile |
src/script/components/Conversation/ConversationCells/CellsTable/CellsTableColumns/CellsTableRowOptions/CellsTableRowOptions.tsx |
Add "Edit" option for editable files in table row dropdown |
src/script/components/Conversation/ConversationCells/CellsTable/CellsFilePreviewModal/CellsFilePreviewModal.tsx |
Use selectedFile.id instead of context ID, pass isEditMode |
src/script/components/CellsGlobalView/CellsTable/common/CellsFilePreviewModalContext/CellsFilePreviewModalContext.tsx |
Add isEditMode state and parameter to handleOpenFile |
src/script/components/CellsGlobalView/CellsTable/CellsTableColumns/CellsTableRowOptions/CellsTableRowOptions.tsx |
Add "Edit" option for editable files in table row dropdown |
src/script/components/CellsGlobalView/CellsTable/CellsFilePreviewModal/CellsFilePreviewModal.tsx |
Use selectedFile.id instead of context ID, pass isEditMode |
src/i18n/en-US.json |
Added translation keys for edit option and editor error messages |
src/types/i18n.d.ts |
Type definitions for new i18n keys |
| if (fileUrl) { | ||
| const node = await cellsRepository.getNode({uuid: id, flags: []}); | ||
| await forcedDownloadFile({url: node.PreSignedGET?.Url || fileUrl, name: fileNameWithExtension}); |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Important] The handleFileDownload function lacks error handling. If the API call or download fails, the user will get no feedback.
Add try-catch with user-facing error handling:
const handleFileDownload = async () => {
if (!fileUrl) return;
try {
const node = await cellsRepository.getNode({uuid: id, flags: []});
await forcedDownloadFile({url: node.PreSignedGET?.Url || fileUrl, name: fileNameWithExtension});
} catch (error) {
// Show user-facing error notification
console.error('Failed to download file:', error);
// Consider adding a toast notification here
}
};| if (fileUrl) { | |
| const node = await cellsRepository.getNode({uuid: id, flags: []}); | |
| await forcedDownloadFile({url: node.PreSignedGET?.Url || fileUrl, name: fileNameWithExtension}); | |
| if (!fileUrl) return; | |
| try { | |
| const node = await cellsRepository.getNode({uuid: id, flags: []}); | |
| await forcedDownloadFile({url: node.PreSignedGET?.Url || fileUrl, name: fileNameWithExtension}); | |
| } catch (error) { | |
| // Show user-facing error notification | |
| console.error('Failed to download file:', error); | |
| // If a toast notification system is available, use it: | |
| // toast.error('Failed to download file. Please try again.'); | |
| // Otherwise, fallback to alert: | |
| alert('Failed to download file. Please try again.'); |
| export const FileEditor = ({id}: FileEditorProps) => { | ||
| const cellsRepository = container.resolve(CellsRepository); | ||
| const [node, setNode] = useState<Node | null>(null); | ||
| const [isLoading, setIsLoading] = useState(true); | ||
| const [isError, setIsError] = useState(false); | ||
|
|
||
| const fetchNode = useCallback(async () => { | ||
| try { | ||
| setIsLoading(true); | ||
| setIsError(false); | ||
| const fetchedNode = await cellsRepository.getNode({uuid: id, flags: ['WithEditorURLs']}); | ||
| setNode(fetchedNode); | ||
| } catch (err) { | ||
| setIsError(true); | ||
| } finally { | ||
| setIsLoading(false); | ||
| } | ||
| }, [id, cellsRepository]); | ||
|
|
||
| // Initial fetch | ||
| useEffect(() => { | ||
| void fetchNode(); | ||
| }, [id, cellsRepository, fetchNode]); | ||
|
|
||
| // Auto-refresh mechanism before expiry | ||
| useEffect(() => { | ||
| if (!node?.EditorURLs?.collabora.ExpiresAt) { | ||
| return; | ||
| } | ||
|
|
||
| const expiresInSeconds = Number(node.EditorURLs.collabora.ExpiresAt); | ||
| const refreshInSeconds = expiresInSeconds - REFRESH_BUFFER_SECONDS; | ||
|
|
||
| // Set timeout to refresh before expiry | ||
| const timeoutId = setTimeout(() => { | ||
| void fetchNode(); | ||
| }, refreshInSeconds * MILLISECONDS_IN_SECOND); | ||
|
|
||
| return () => { | ||
| clearTimeout(timeoutId); | ||
| }; | ||
| }, [node, fetchNode]); | ||
|
|
||
| if (isLoading) { | ||
| return <FileLoader />; | ||
| } | ||
|
|
||
| if (isError || !node) { | ||
| return <div>{t('fileFullscreenModal.editor.error')}</div>; | ||
| } | ||
|
|
||
| return ( | ||
| <iframe | ||
| css={styles.editorIframe} | ||
| src={node.EditorURLs?.collabora.Url} | ||
| title={t('fileFullscreenModal.editor.iframeTitle')} | ||
| /> | ||
| ); | ||
| }; |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Important] The new FileEditor component lacks test coverage. Given its security-sensitive nature (rendering iframes with external URLs), it should have comprehensive tests covering:
- URL validation scenarios
- Error states
- Loading states
- Timeout refresh logic
- Edge cases with expiry times
Consider adding tests in a new FileEditor.test.tsx file.
| // Set timeout to refresh before expiry | ||
| const timeoutId = setTimeout(() => { | ||
| void fetchNode(); | ||
| }, refreshInSeconds * MILLISECONDS_IN_SECOND); | ||
|
|
||
| return () => { | ||
| clearTimeout(timeoutId); | ||
| }; |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Blocker] The timeout calculation can create negative or zero timeouts when expiresInSeconds is less than or equal to REFRESH_BUFFER_SECONDS (10 seconds). This will cause immediate re-fetching in a loop.
Add validation:
const expiresInSeconds = Number(node.EditorURLs.collabora.ExpiresAt);
const refreshInSeconds = Math.max(0, expiresInSeconds - REFRESH_BUFFER_SECONDS);
// Only set timeout if there's meaningful time left
if (refreshInSeconds > 0) {
const timeoutId = setTimeout(() => {
void fetchNode();
}, refreshInSeconds * MILLISECONDS_IN_SECOND);
return () => clearTimeout(timeoutId);
}| // Set timeout to refresh before expiry | |
| const timeoutId = setTimeout(() => { | |
| void fetchNode(); | |
| }, refreshInSeconds * MILLISECONDS_IN_SECOND); | |
| return () => { | |
| clearTimeout(timeoutId); | |
| }; | |
| // Only set timeout if there's meaningful time left | |
| if (refreshInSeconds > 0) { | |
| const timeoutId = setTimeout(() => { | |
| void fetchNode(); | |
| }, refreshInSeconds * MILLISECONDS_IN_SECOND); | |
| return () => { | |
| clearTimeout(timeoutId); | |
| }; | |
| } |
| <iframe | ||
| css={styles.editorIframe} | ||
| src={node.EditorURLs?.collabora.Url} | ||
| title={t('fileFullscreenModal.editor.iframeTitle')} | ||
| /> |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Important] The iframe lacks security attributes recommended for embedding external content. Add sandbox and other security attributes:
<iframe
css={styles.editorIframe}
src={node.EditorURLs?.collabora.Url}
title={t('fileFullscreenModal.editor.iframeTitle')}
sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-modals"
referrerPolicy="no-referrer"
/>Note: Adjust the sandbox permissions based on actual Collabora requirements - use the most restrictive set that still allows the editor to function.
| <button | ||
| title="Viewing" | ||
| aria-label="Viewing" | ||
| className={!isInEditMode ? 'active' : ''} | ||
| onClick={() => onEditModeChange(false)} | ||
| > | ||
| <ShowIcon width={16} height={16} /> | ||
| Viewing | ||
| </button> | ||
| <button | ||
| title="Editing" | ||
| aria-label="Editing" | ||
| className={isInEditMode ? 'active' : ''} | ||
| onClick={() => onEditModeChange(true)} | ||
| > | ||
| <EditIcon width={14} height={14} /> | ||
| Editing | ||
| </button> | ||
| </div> |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Important] The toggle buttons lack proper accessibility attributes. They should include role="button", type="button", and use aria-pressed instead of relying only on CSS classes for state indication.
<button
type="button"
role="button"
title="Viewing"
aria-label="Viewing"
aria-pressed={!isInEditMode}
className={!isInEditMode ? 'active' : ''}
onClick={() => onEditModeChange(false)}
>
<ShowIcon width={16} height={16} />
Viewing
</button>Apply the same pattern to the "Editing" button with aria-pressed={isInEditMode}.
| const refreshInSeconds = expiresInSeconds - REFRESH_BUFFER_SECONDS; | ||
|
|
||
| // Set timeout to refresh before expiry | ||
| const timeoutId = setTimeout(() => { | ||
| void fetchNode(); | ||
| }, refreshInSeconds * MILLISECONDS_IN_SECOND); | ||
|
|
||
| return () => { | ||
| clearTimeout(timeoutId); | ||
| }; |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Bug] Using Number() on ExpiresAt can produce NaN if the value is not a valid number. This would make refreshInSeconds also NaN, leading to unexpected behavior. Add validation:
const expiresInSeconds = Number(node.EditorURLs.collabora.ExpiresAt);
if (isNaN(expiresInSeconds) || expiresInSeconds <= 0) {
return;
}
const refreshInSeconds = Math.max(0, expiresInSeconds - REFRESH_BUFFER_SECONDS);
if (refreshInSeconds > 0) {
const timeoutId = setTimeout(() => {
void fetchNode();
}, refreshInSeconds * MILLISECONDS_IN_SECOND);
return () => clearTimeout(timeoutId);
}| const refreshInSeconds = expiresInSeconds - REFRESH_BUFFER_SECONDS; | |
| // Set timeout to refresh before expiry | |
| const timeoutId = setTimeout(() => { | |
| void fetchNode(); | |
| }, refreshInSeconds * MILLISECONDS_IN_SECOND); | |
| return () => { | |
| clearTimeout(timeoutId); | |
| }; | |
| if (isNaN(expiresInSeconds) || expiresInSeconds <= 0) { | |
| return; | |
| } | |
| const refreshInSeconds = Math.max(0, expiresInSeconds - REFRESH_BUFFER_SECONDS); | |
| // Set timeout to refresh before expiry | |
| if (refreshInSeconds > 0) { | |
| const timeoutId = setTimeout(() => { | |
| void fetchNode(); | |
| }, refreshInSeconds * MILLISECONDS_IN_SECOND); | |
| return () => { | |
| clearTimeout(timeoutId); | |
| }; | |
| } |
| if (fileUrl) { | ||
| const node = await cellsRepository.getNode({uuid: id, flags: []}); | ||
| await forcedDownloadFile({url: node.PreSignedGET?.Url || fileUrl, name: fileNameWithExtension}); |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Important] The download function fetches fresh node data but doesn't validate that PreSignedGET?.Url is present before falling back to fileUrl. If both are undefined or invalid URLs, the download may fail silently. Add validation:
const handleFileDownload = async () => {
if (!fileUrl) return;
try {
const node = await cellsRepository.getNode({uuid: id, flags: []});
const downloadUrl = node.PreSignedGET?.Url || fileUrl;
if (!downloadUrl) {
console.error('No valid download URL available');
return;
}
await forcedDownloadFile({url: downloadUrl, name: fileNameWithExtension});
} catch (error) {
console.error('Failed to download file:', error);
}
};| if (fileUrl) { | |
| const node = await cellsRepository.getNode({uuid: id, flags: []}); | |
| await forcedDownloadFile({url: node.PreSignedGET?.Url || fileUrl, name: fileNameWithExtension}); | |
| if (!fileUrl) { | |
| // No fileUrl provided, cannot proceed | |
| console.error('No fileUrl provided for download'); | |
| return; | |
| } | |
| try { | |
| const node = await cellsRepository.getNode({uuid: id, flags: []}); | |
| const downloadUrl = node.PreSignedGET?.Url || fileUrl; | |
| if (!downloadUrl || typeof downloadUrl !== 'string' || downloadUrl.trim() === '') { | |
| console.error('No valid download URL available'); | |
| return; | |
| } | |
| await forcedDownloadFile({url: downloadUrl, name: fileNameWithExtension}); | |
| } catch (error) { | |
| console.error('Failed to download file:', error); |
|
|
||
| const EDITABLE_FILE_EXTENSIONS = ['odf', 'docx', 'xlsx', 'pptx']; | ||
|
|
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] [Suggestion] The isFileEditable function and EDITABLE_FILE_EXTENSIONS constant lack JSDoc documentation explaining what makes a file editable and the business logic behind the supported extensions:
/**
* File extensions that support collaborative editing via Collabora integration.
* Includes modern Office formats (docx, xlsx, pptx) and OpenDocument formats (odf).
*/
const EDITABLE_FILE_EXTENSIONS = ['odf', 'docx', 'xlsx', 'pptx'];
/**
* Checks if a file extension is supported for collaborative editing.
*
* @param fileExtension - The file extension to check (without the leading dot)
* @returns true if the file can be edited with Collabora, false otherwise
*
* @example
* isFileEditable('docx') // returns true
* isFileEditable('pdf') // returns false
*/
export const isFileEditable = (fileExtension: string): boolean => {
return EDITABLE_FILE_EXTENSIONS.includes(fileExtension.toLowerCase());
};| const EDITABLE_FILE_EXTENSIONS = ['odf', 'docx', 'xlsx', 'pptx']; | |
| /** | |
| * List of file extensions that are supported for collaborative editing via Collabora integration. | |
| * | |
| * Business logic: | |
| * - Only modern Office formats (docx, xlsx, pptx) and OpenDocument format (odf) are supported. | |
| * - These formats can be edited collaboratively in the application. | |
| * - Other formats (e.g., pdf, txt) are not supported for editing. | |
| */ | |
| const EDITABLE_FILE_EXTENSIONS = ['odf', 'docx', 'xlsx', 'pptx']; | |
| /** | |
| * Checks if a file extension is supported for collaborative editing. | |
| * | |
| * @param fileExtension - The file extension to check (without the leading dot). | |
| * @returns {boolean} True if the file can be edited with Collabora, false otherwise. | |
| * | |
| * @example | |
| * isFileEditable('docx') // returns true | |
| * isFileEditable('pdf') // returns false | |
| */ |
| <iframe | ||
| css={styles.editorIframe} | ||
| src={node.EditorURLs?.collabora.Url} | ||
| title={t('fileFullscreenModal.editor.iframeTitle')} | ||
| /> |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Important] The iframe src attribute uses an unsanitized URL from the API response (node.EditorURLs?.collabora.Url). While this URL comes from a trusted backend, it should still be validated to ensure it uses HTTPS protocol and doesn't contain javascript: or data: schemes.
Consider adding URL validation:
const validateEditorUrl = (url: string): boolean => {
try {
const parsed = new URL(url);
return parsed.protocol === 'https:';
} catch {
return false;
}
};
// Then in the render:
if (!node.EditorURLs?.collabora.Url || !validateEditorUrl(node.EditorURLs.collabora.Url)) {
return <div>{t('fileFullscreenModal.editor.error')}</div>;
}| const [isEditableState, setIsEditableState] = useState(isEditMode); | ||
| const isEditable = isFileEditable(fileExtension); | ||
|
|
||
| const onCloseModal = () => { | ||
| setIsEditableState(false); | ||
| onClose(); | ||
| }; | ||
|
|
||
| useEffect(() => { | ||
| setIsEditableState(!!isEditMode); | ||
| }, [isEditMode]); |
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] [Suggestion] The variable name isEditableState is somewhat redundant. Since it's already a local state variable, consider renaming to isInEditMode to match the prop name used in FileHeader (isInEditMode), improving consistency:
const [isInEditMode, setIsInEditMode] = useState(isEditMode);
const isEditable = isFileEditable(fileExtension);
const onCloseModal = () => {
setIsInEditMode(false);
onClose();
};
useEffect(() => {
setIsInEditMode(!!isEditMode);
}, [isEditMode]);|
🔗 Download Full Report Artifact 🧪 Playwright Test Summary
Failed Tests:❌ Team owner adds whole team to an all team chat (tags: TC-8631, crit-flow-web)Location: specs/CriticalFlow/addMembersToChat-TC-8631.spec.ts:43 Errors: ❌ Planning group call with sending various messages during call (tags: TC-8632, crit-flow-web)Location: specs/CriticalFlow/groupCalls-TC-8632.spec.ts:37 Errors: ❌ Group Video call (tags: TC-8637, crit-flow-web)Location: specs/CriticalFlow/groupVideoCall-TC-8637.spec.ts:39 Errors: ❌ New person joins team and setups up device (tags: TC-8635, crit-flow-web)Location: specs/CriticalFlow/joinTeam-TC-8635.spec.ts:38 Errors: Flaky Tests: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 31 out of 33 changed files in this pull request and generated 3 comments.
| const fetchNode = useCallback(async () => { | ||
| try { | ||
| setIsLoading(true); | ||
| setIsError(false); | ||
| const fetchedNode = await cellsRepository.getNode({uuid: id, flags: ['WithEditorURLs']}); | ||
| setNode(fetchedNode); | ||
| } catch (err) { | ||
| setIsError(true); | ||
| } finally { | ||
| setIsLoading(false); | ||
| } | ||
| }, [id, cellsRepository]); |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Suggestion] The error handling doesn't capture or log the error details, making debugging difficult. When the API call fails, the error is silently swallowed.
Recommendation: Add proper error logging:
const fetchNode = useCallback(async () => {
try {
setIsLoading(true);
setIsError(false);
const fetchedNode = await cellsRepository.getNode({uuid: id, flags: ['WithEditorURLs']});
setNode(fetchedNode);
} catch (err) {
console.error('Failed to fetch editor URLs:', err);
setIsError(true);
} finally {
setIsLoading(false);
}
}, [id, cellsRepository]);|
|
||
| export const editorIframe: CSSObject = { | ||
| width: '100%', | ||
| height: '100%', |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] [Suggestion] The border styling appears to be missing from the iframe. For better visual consistency and to clearly separate the embedded content from the parent UI, consider adding a border property:
export const editorIframe: CSSObject = {
width: '100%',
height: '100%',
border: 'none', // or '1px solid #ccc' if a border is desired
};| height: '100%', | |
| height: '100%', | |
| border: '1px solid #ccc', // Ensures visual separation of iframe content |
| export const FileEditor = ({id}: FileEditorProps) => { | ||
| const cellsRepository = container.resolve(CellsRepository); | ||
| const [node, setNode] = useState<Node | null>(null); | ||
| const [isLoading, setIsLoading] = useState(true); | ||
| const [isError, setIsError] = useState(false); | ||
|
|
||
| const fetchNode = useCallback(async () => { | ||
| try { | ||
| setIsLoading(true); | ||
| setIsError(false); | ||
| const fetchedNode = await cellsRepository.getNode({uuid: id, flags: ['WithEditorURLs']}); | ||
| setNode(fetchedNode); | ||
| } catch (err) { | ||
| setIsError(true); | ||
| } finally { | ||
| setIsLoading(false); | ||
| } | ||
| }, [id, cellsRepository]); | ||
|
|
||
| // Initial fetch | ||
| useEffect(() => { | ||
| void fetchNode(); | ||
| }, [id, cellsRepository, fetchNode]); | ||
|
|
||
| // Auto-refresh mechanism before expiry | ||
| useEffect(() => { | ||
| if (!node?.EditorURLs?.collabora.ExpiresAt) { | ||
| return undefined; | ||
| } | ||
|
|
||
| const expiresInSeconds = Number(node.EditorURLs.collabora.ExpiresAt); | ||
| const refreshInSeconds = expiresInSeconds - REFRESH_BUFFER_SECONDS; | ||
|
|
||
| // Set timeout to refresh before expiry | ||
| const timeoutId = setTimeout(() => { | ||
| void fetchNode(); | ||
| }, refreshInSeconds * MILLISECONDS_IN_SECOND); | ||
|
|
||
| return () => { | ||
| clearTimeout(timeoutId); | ||
| }; | ||
| }, [node, fetchNode]); | ||
|
|
||
| if (isLoading) { | ||
| return <FileLoader />; | ||
| } | ||
|
|
||
| if (isError || !node) { | ||
| return <div>{t('fileFullscreenModal.editor.error')}</div>; | ||
| } | ||
|
|
||
| return ( | ||
| <iframe | ||
| css={styles.editorIframe} | ||
| src={node.EditorURLs?.collabora.Url} | ||
| title={t('fileFullscreenModal.editor.iframeTitle')} | ||
| /> | ||
| ); | ||
| }; |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Suggestion] The new FileEditor component lacks test coverage. Given that other components in the codebase have comprehensive tests (e.g., FileTypeUtil.test.ts, FileAssetOptions.test.tsx), this critical component handling iframe integration should also have tests.
Recommendation: Add tests covering:
- Loading state display
- Error state display
- Successful iframe rendering
- URL refresh logic and timer handling
- Handling of missing or invalid EditorURLs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 31 out of 33 changed files in this pull request and generated 2 comments.
| it('returns false for similar but unsupported extensions', () => { | ||
| expect(isFileEditable('odt')).toBe(false); | ||
| expect(isFileEditable('ods')).toBe(false); | ||
| expect(isFileEditable('odp')).toBe(false); | ||
| }); |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Important] The test suite explicitly verifies that odt, ods, and odp (standard OpenDocument formats) return false from isFileEditable(), while odf returns true. This seems backwards - .odt is the standard OpenDocument Text format that would typically be edited with Collabora, while .odf is for formulas.
If Collabora is meant to edit standard office documents, the editable list should likely include:
odt(OpenDocument Text) instead of or in addition toodf- Potentially
ods(Spreadsheets) andodp(Presentations)
Recommendation: Verify with the Collabora integration requirements which formats are actually supported, and update both the EDITABLE_FILE_EXTENSIONS constant and these tests accordingly.
|
|
||
| export const editorIframe: CSSObject = { | ||
| width: '100%', | ||
| height: '100%', |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] [Suggestion] The iframe styling should include border: 'none' to remove the default iframe border, which is inconsistent with modern UI design.
Recommendation:
export const editorIframe: CSSObject = {
width: '100%',
height: '100%',
border: 'none',
};| height: '100%', | |
| height: '100%', | |
| border: 'none', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 31 out of 33 changed files in this pull request and generated 4 comments.
| const expiresInSeconds = Number(node.EditorURLs.collabora.ExpiresAt); | ||
| const refreshInSeconds = expiresInSeconds - REFRESH_BUFFER_SECONDS; | ||
|
|
||
| // Set timeout to refresh before expiry | ||
| const timeoutId = setTimeout(() => { | ||
| void fetchNode(); | ||
| }, refreshInSeconds * MILLISECONDS_IN_SECOND); |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Important] Potential for extremely large or negative timeout values. If ExpiresAt is very large or refreshInSeconds is negative, this could cause issues.
Add validation:
const expiresInSeconds = Number(node.EditorURLs.collabora.ExpiresAt);
// Validate the expiry time is reasonable
if (isNaN(expiresInSeconds) || expiresInSeconds <= 0 || expiresInSeconds > 86400) {
// Invalid or unreasonable expiry (> 24 hours)
return undefined;
}
const refreshInSeconds = expiresInSeconds - REFRESH_BUFFER_SECONDS;
// Don't set timeout if already expired or refresh time is negative
if (refreshInSeconds <= 0) {
return undefined;
}
const timeoutId = setTimeout(() => {
void fetchNode();
}, refreshInSeconds * MILLISECONDS_IN_SECOND);This prevents setting invalid timeouts that could cause unexpected behavior.
| const handleFileDownload = async () => { | ||
| if (fileUrl) { | ||
| const node = await cellsRepository.getNode({uuid: id}); | ||
| await forcedDownloadFile({url: node.PreSignedGET?.Url || fileUrl, name: fileNameWithExtension}); | ||
| } | ||
| }; |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Important] The download URL from node.PreSignedGET?.Url is not validated before use. If the API returns a malicious URL, this could lead to security issues.
Add URL validation:
import {sanitizeUrl} from 'Components/InputBar/InputBarEditor/RichTextEditor/utils/url';
const handleFileDownload = async () => {
if (fileUrl) {
const node = await cellsRepository.getNode({uuid: id});
const downloadUrl = node.PreSignedGET?.Url || fileUrl;
const sanitizedUrl = sanitizeUrl(downloadUrl);
if (!sanitizedUrl) {
// Handle invalid URL error
return;
}
await forcedDownloadFile({url: sanitizedUrl, name: fileNameWithExtension});
}
};This ensures only valid HTTPS URLs are used for downloads.
| if (isError || !node) { | ||
| return <div>{t('fileFullscreenModal.editor.error')}</div>; | ||
| } |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] [Suggestion] The error state renders a plain <div> with text, which is inconsistent with how errors are handled elsewhere in FileFullscreenModal (e.g., NoPreviewAvailable uses FilePlaceholder).
For consistency, use a proper error UI component:
import {FilePlaceholder} from '../common/FilePlaceholder/FilePlaceholder';
if (isError || !node) {
return (
<FilePlaceholder
title={t('fileFullscreenModal.editor.error')}
description={t('fileFullscreenModal.editor.errorDescription')}
/>
);
}This provides a better user experience with properly styled error messaging.
| fileUrl?: string; | ||
| isEditable?: boolean; | ||
| isInEditMode?: boolean; | ||
| onEditModeChange: (isEditable: boolean) => void; |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Suggestion] The parameter name isEditable in the onEditModeChange callback is misleading. The parameter actually represents whether edit mode should be enabled, not whether the file is editable.
Rename for clarity:
onEditModeChange: (shouldEnableEditMode: boolean) => void;This makes it clear that the parameter controls the edit mode state, not file editability.
| onEditModeChange: (isEditable: boolean) => void; | |
| onEditModeChange: (shouldEnableEditMode: boolean) => void; |
| const {handleOpenFile} = useCellsFilePreviewModal(); | ||
|
|
||
| const url = node.url; | ||
| const name = node.type === 'folder' ? `${node.name}.zip` : node.name; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moving these folder and file into enum would be better
This can be tackled in another PR.
|
|
||
| import {FileLoader} from '../FileLoader/FileLoader'; | ||
|
|
||
| const MILLISECONDS_IN_SECOND = 1000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use TIME_IN_MILLIS.SECOND instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 31 out of 33 changed files in this pull request and generated 2 comments.
| useEffect(() => { | ||
| if (!node?.EditorURLs?.collabora.ExpiresAt) { | ||
| return undefined; | ||
| } | ||
|
|
||
| const expiresInSeconds = Number(node.EditorURLs.collabora.ExpiresAt); | ||
| const refreshInSeconds = expiresInSeconds - REFRESH_BUFFER_SECONDS; | ||
|
|
||
| // Set timeout to refresh before expiry | ||
| const timeoutId = setTimeout(() => { | ||
| void fetchNode(); | ||
| }, refreshInSeconds * MILLISECONDS_IN_SECOND); | ||
|
|
||
| return () => { | ||
| clearTimeout(timeoutId); | ||
| }; | ||
| }, [node, fetchNode]); |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] [Suggestion] The auto-refresh effect could cause memory leaks if fetchNode changes frequently. The dependency array includes fetchNode, which is memoized with useCallback, but if the component re-renders and fetchNode is recreated, a new timeout will be set without clearing the old one properly.
Consider removing fetchNode from the dependency array and using a ref pattern:
useEffect(() => {
if (!node?.EditorURLs?.collabora.ExpiresAt) {
return undefined;
}
const expiresInSeconds = Number(node.EditorURLs.collabora.ExpiresAt);
const refreshInSeconds = Math.max(0, expiresInSeconds - REFRESH_BUFFER_SECONDS);
if (refreshInSeconds <= 0) {
return undefined;
}
const timeoutId = setTimeout(() => {
void fetchNode();
}, refreshInSeconds * MILLISECONDS_IN_SECOND);
return () => {
clearTimeout(timeoutId);
};
}, [node]); // Remove fetchNode from dependencies| setIsError(false); | ||
| const fetchedNode = await cellsRepository.getNode({uuid: id, flags: ['WithEditorURLs']}); | ||
| setNode(fetchedNode); | ||
| } catch (err) { |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] [Suggestion] Error handling is incomplete - the err is caught but not logged. This makes debugging production issues difficult.
Add error logging:
} catch (err) {
console.error('Failed to fetch node with editor URLs:', err);
setIsError(true);
}| } catch (err) { | |
| } catch (err) { | |
| console.error('Failed to fetch node with editor URLs:', err); |
…om/wireapp/wire-webapp into feat/integrate-collabora-WPB-21650
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## dev #19813 +/- ##
==========================================
- Coverage 43.78% 43.71% -0.08%
==========================================
Files 1296 1298 +2
Lines 32637 32707 +70
Branches 7244 7259 +15
==========================================
+ Hits 14290 14297 +7
- Misses 16631 16693 +62
- Partials 1716 1717 +1 🚀 New features to boost your workflow:
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 58 out of 60 changed files in this pull request and generated no new comments.
* initial commit * add close modal handler * added isFileEditable() * added edit option for conversation assets * add tests * fixed getNode api call * bump @webapp/core * fix package.json * fixed package.json * fix package.json * address PR comments * fixed types
* fix: remove call from the call state when a user is left the group (#19790) * chore(deps-dev): bump rimraf from 6.1.0 to 6.1.2 in /server (#19791) Bumps [rimraf](https://github.com/isaacs/rimraf) from 6.1.0 to 6.1.2. - [Changelog](https://github.com/isaacs/rimraf/blob/main/CHANGELOG.md) - [Commits](isaacs/rimraf@v6.1.0...v6.1.2) --- updated-dependencies: - dependency-name: rimraf dependency-version: 6.1.2 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * refactor(WPB-21957): create fixture for creating teams + refactor edit tests with it (#19804) This is an attempt to resolve the race conditions happening when two users connect in a 1:1 for the first time starting the conversation as proteus but it's migrated to MLS automatically. This leads to a message sent during the migration being lost. Team members don't need to go through this step as they are aware of the spoken protocol of other members after login. * test(WPB-19966): write "Reply" regression tests (#19760) * test(TC-8038): add test for not replying to a ping * test(TC-8039): add test for not replying to timed messages * test(TC-2994): add test for quote in reply to vanish if source message is removed * test(TC-2996): add test for searching message * test(TC-2997): test for quote in reply to be truncated * test(TC-3002): reply to a picture * test(TC-3003): reply to an audio message * test(TC-3004): reply to video * test(TC-3005): reply to link * test(TC3006): reply to file * test(TC-3007): reply to reply * test(TC-3008): reply to link with text * test(TC-3011): Reply with timed message * test(TC-3013): test clicking the reply * test(TC-3014): test replying in a conversation I'm no longer part of * test(TC-3016): click on mention in reply opens user profile * fix: remove visibility check from sendMessage * test(TC-3009): add test case for replying to a location + util for sending location via testservice * refactor: replace createPagesForUser with new fixtures * refactor(test): use new fixtures for reply tests * refactor: remove no longer used PagePlugin withConversation * fix: accessibility improvements login(https://wearezeta.atlassian.net/browse/WPB-20819) (#19714) * fix: make password toggle button accessible and localised(WPB-21228) * fix: translate type * fix: Login - New view is not announced * fix: make back button accessible WPB-21466 * fix: make external link 2fa accessible(WPB-21279) * fix: password toggle button text alternative(WPB-21228) * fix: make verify account header focusable using screenkey and login subheading style adjustments * fix: add toggle password show/hide label * fix: address review comments * chore: bump core packages * fix: pipeline issues * fix: PR comments * fix: pipeline issues * chore(deps): bump @wireapp/core from 46.46.3 to 46.46.5 (#19793) Bumps [@wireapp/core](https://github.com/wireapp/wire-web-packages) from 46.46.3 to 46.46.5. - [Commits](https://github.com/wireapp/wire-web-packages/compare/@wireapp/[email protected]...@wireapp/[email protected]) --- updated-dependencies: - dependency-name: "@wireapp/core" dependency-version: 46.46.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump core-js from 3.46.0 to 3.47.0 (#19797) Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.46.0 to 3.47.0. - [Release notes](https://github.com/zloirock/core-js/releases) - [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md) - [Commits](https://github.com/zloirock/core-js/commits/v3.47.0/packages/core-js) --- updated-dependencies: - dependency-name: core-js dependency-version: 3.47.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump emoji-picker-react from 4.15.1 to 4.15.2 (#19802) Bumps [emoji-picker-react](https://github.com/ealush/emoji-picker-react) from 4.15.1 to 4.15.2. - [Release notes](https://github.com/ealush/emoji-picker-react/releases) - [Commits](https://github.com/ealush/emoji-picker-react/commits) --- updated-dependencies: - dependency-name: emoji-picker-react dependency-version: 4.15.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump html-webpack-plugin from 5.6.4 to 5.6.5 (#19800) Bumps [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) from 5.6.4 to 5.6.5. - [Release notes](https://github.com/jantimon/html-webpack-plugin/releases) - [Changelog](https://github.com/jantimon/html-webpack-plugin/blob/main/CHANGELOG.md) - [Commits](jantimon/html-webpack-plugin@v5.6.4...v5.6.5) --- updated-dependencies: - dependency-name: html-webpack-plugin dependency-version: 5.6.5 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump oidc-client-ts from 3.4.0 to 3.4.1 (#19801) Bumps [oidc-client-ts](https://github.com/authts/oidc-client-ts) from 3.4.0 to 3.4.1. - [Release notes](https://github.com/authts/oidc-client-ts/releases) - [Commits](authts/oidc-client-ts@v3.4.0...v3.4.1) --- updated-dependencies: - dependency-name: oidc-client-ts dependency-version: 3.4.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump webpack from 5.102.1 to 5.103.0 (#19796) Bumps [webpack](https://github.com/webpack/webpack) from 5.102.1 to 5.103.0. - [Release notes](https://github.com/webpack/webpack/releases) - [Commits](webpack/webpack@v5.102.1...v5.103.0) --- updated-dependencies: - dependency-name: webpack dependency-version: 5.103.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump workbox-webpack-plugin from 7.3.0 to 7.4.0 (#19799) Bumps [workbox-webpack-plugin](https://github.com/googlechrome/workbox) from 7.3.0 to 7.4.0. - [Release notes](https://github.com/googlechrome/workbox/releases) - [Commits](GoogleChrome/workbox@v7.3.0...v7.4.0) --- updated-dependencies: - dependency-name: workbox-webpack-plugin dependency-version: 7.4.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump stylelint from 16.25.0 to 16.26.0 (#19798) Bumps [stylelint](https://github.com/stylelint/stylelint) from 16.25.0 to 16.26.0. - [Release notes](https://github.com/stylelint/stylelint/releases) - [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md) - [Commits](stylelint/stylelint@16.25.0...16.26.0) --- updated-dependencies: - dependency-name: stylelint dependency-version: 16.26.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump baseline-browser-mapping from 2.8.28 to 2.8.31 (#19792) Bumps [baseline-browser-mapping](https://github.com/web-platform-dx/baseline-browser-mapping) from 2.8.28 to 2.8.31. - [Release notes](https://github.com/web-platform-dx/baseline-browser-mapping/releases) - [Commits](web-platform-dx/baseline-browser-mapping@v2.8.28...v2.8.31) --- updated-dependencies: - dependency-name: baseline-browser-mapping dependency-version: 2.8.31 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * test(WPB-19968): add tests for self deleting messages (#19805) * test(TC-657): add test for sending ephemeral text message in 1:1 * test(TC-658): add test for sending ephemeral text message in group * refactor: replace util sendTimedMessage with dedicated utils for enabling and disabling timed messages * test(TC-662): Verify timer is applied to all messages until turning it off in 1:1 * test(TC-664): Verify that message with previous timer are deleted on start-up when the timeout passed in 1:1 * refactor: overload createPage fixture to optionally accept a context to reuse * refactor: use team for tests using new fixture * test(TC-675): Verify the message is not deleted for users that didn't read the message * test(TC-3715): set global group conversation timer * refactor(reply-tests): remove unused createUser fixture * test(TC-3716): check current time is visible in details * fix(a11y): add disabled attribute to MessageTimerButton * test(TC-3718): check timed message button is disabled if timed messages are set globally * test(TC-3719): globally set timer is shown on button next to input field * test(TC-3720): system messages are shown for enabled / disabled timer messages * test(TC-3717): check ephemeral message appear in search results * test(TC-3731): add test for message to disappear from search results (currently broken) * refactor: group search tests * refactor: update search result tests to do assertions on receiver side * refactor: group tests with self deleting messages set globally for a group conversation * docs: add ticket number to comment for skipped test * fix: prevent microphone disabled dialog display when muted (#19808) * test(WPB-21957): update backend endpoint to match api version (#19809) * chore: bump avs to v10.2.19 (#19810) * chore(deps): bump pm2 from 6.0.13 to 6.0.14 in /server (#19814) Bumps [pm2](https://github.com/Unitech/pm2) from 6.0.13 to 6.0.14. - [Release notes](https://github.com/Unitech/pm2/releases) - [Changelog](https://github.com/Unitech/pm2/blob/master/CHANGELOG.md) - [Commits](Unitech/pm2@v6.0.13...v6.0.14) --- updated-dependencies: - dependency-name: pm2 dependency-version: 6.0.14 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump js-yaml from 3.14.1 to 3.14.2 in /server (#19817) Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 3.14.1 to 3.14.2. - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](nodeca/js-yaml@3.14.1...3.14.2) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 3.14.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * test(WPB-19939): add authentication regression tests (#19826) * test(TC-34579: verify signin button is disabled inc ase of empty credentials * test(TC-3468): Verify sign in error appearance in case of suspended team account * test(TC-3460): Verify current browser is set as temporary device * test(TC-3465): Verify sign in error appearance in case of wrong credentials * test(TC-3472): Ensure history is kept after refresh on permanent device * test(TC-3473): create data driven test to also ensure history is kept on temporary device * test(TC-1311): verify session expires * test(TC-3480): check tls versions allowed by webapp server * test(TC-1311): Ensure history is gone after logging out of public computer * fix(websocket): optimise event handling. Add heartbeat [WPB-21950] (#19825) * fix(lifecycle): optimise online / offline event handling. Add heartbeat for WS * Update src/script/repositories/event/EventRepository.ts Co-authored-by: Copilot <[email protected]> * Update src/script/repositories/event/EventRepository.ts Co-authored-by: Copilot <[email protected]> * Update src/script/repositories/event/EventRepository.ts Co-authored-by: Copilot <[email protected]> * chore: rename to updateConnectivityStatus * chore: add copilot suggested improvements --------- Co-authored-by: Copilot <[email protected]> * chore(deps): bump express from 4.21.2 to 4.22.0 in /server (#19827) Bumps [express](https://github.com/expressjs/express) from 4.21.2 to 4.22.0. - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/4.22.0/History.md) - [Commits](expressjs/express@4.21.2...4.22.0) --- updated-dependencies: - dependency-name: express dependency-version: 4.22.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore: blocking user spec [19940] (#19784) * test(WPB-19940): add tests for blocking users * test(block): refactor block.spec.ts according to Review-Comments add function to userActions.ts to send a connection request add fixture for connection request delete conversationNotConnected.modal.ts, replace it with acknowledge.modal.ts * test(block): refactor block.spec.ts according to Review-Comments * test(block): refactor block.spec.ts according to Review-Comments * test(block): fixed unclear comments and variable namings --------- Co-authored-by: Klaus Boldt <[email protected]> * chore(deps): bump crowdin/github-action from 2.12.0 to 2.13.0 (#19828) Bumps [crowdin/github-action](https://github.com/crowdin/github-action) from 2.12.0 to 2.13.0. - [Release notes](https://github.com/crowdin/github-action/releases) - [Commits](crowdin/github-action@v2.12.0...v2.13.0) --- updated-dependencies: - dependency-name: crowdin/github-action dependency-version: 2.13.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat: integrate Collabora using iframe [WPB-21650] (#19813) * initial commit * add close modal handler * added isFileEditable() * added edit option for conversation assets * add tests * fixed getNode api call * bump @webapp/core * fix package.json * fixed package.json * fix package.json * address PR comments * fixed types * chore(deps-dev): bump stylelint from 16.26.0 to 16.26.1 (#19820) Bumps [stylelint](https://github.com/stylelint/stylelint) from 16.26.0 to 16.26.1. - [Release notes](https://github.com/stylelint/stylelint/releases) - [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md) - [Commits](stylelint/stylelint@16.26.0...16.26.1) --- updated-dependencies: - dependency-name: stylelint dependency-version: 16.26.1 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @playwright/test from 1.56.1 to 1.57.0 (#19818) Bumps [@playwright/test](https://github.com/microsoft/playwright) from 1.56.1 to 1.57.0. - [Release notes](https://github.com/microsoft/playwright/releases) - [Commits](microsoft/playwright@v1.56.1...v1.57.0) --- updated-dependencies: - dependency-name: "@playwright/test" dependency-version: 1.57.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump baseline-browser-mapping from 2.8.31 to 2.8.32 (#19819) Bumps [baseline-browser-mapping](https://github.com/web-platform-dx/baseline-browser-mapping) from 2.8.31 to 2.8.32. - [Release notes](https://github.com/web-platform-dx/baseline-browser-mapping/releases) - [Commits](web-platform-dx/baseline-browser-mapping@v2.8.31...v2.8.32) --- updated-dependencies: - dependency-name: baseline-browser-mapping dependency-version: 2.8.32 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump emoji-picker-react from 4.15.2 to 4.16.1 (#19822) Bumps [emoji-picker-react](https://github.com/ealush/emoji-picker-react) from 4.15.2 to 4.16.1. - [Release notes](https://github.com/ealush/emoji-picker-react/releases) - [Commits](https://github.com/ealush/emoji-picker-react/commits) --- updated-dependencies: - dependency-name: emoji-picker-react dependency-version: 4.16.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ci(WPB-21987): shard playwright tests across multiple runners (#19807) * refactor: use nvmrc to select node version * feat: add job to build test service * feat: shard tests across multiple runners with integrated testservice & job to collect reports * fix: build shadowJar of testservice * fix: generate json report when merging blobs * refactor: only download chrome browser for tests * ci: use github reporter in CI * fix: re-use playwright config when merging reports to generate json report for PR comment * refactor: don't pass github user and token when building testservice * feat: use 16 runners for sharding * feat: execute regression tests in addition to critical flow * fix: make script for reporting playwright summary work with nested test suites * chore: use SHA for third party actions (So Sonar shuts up) * refactor: use line reporter instead of github The report annotations are too annoying * refactor: stop background process of testservice after test * fix: run critical flow and regression tests * ci: increase number of parallel test runners to 32 Now that the regression tests and critical flow tests are executed 16 runners is a bit too little * style: ignore prettier for shard definition * chore: safe guard stripAnsi function in report generation * ci(WPB-21987): group test in playwright comment by file (#19830) * refactor: update report script to group tests by file * style: use list to render test cases * feat: add direct link to download playwright report * test(WPB-19966): fix getMessage locator to account for different message states (#19832) * chore: add env var MAX_API_VERSION [WPB-22159] (#19831) * runfix(cells): disable spammy tracking (#19829) * test(WPB-19968): use a unique test message to avoid strict mode violation (#19834) * test(WPB-19939): wait for login to finish before continuing (#19833) * chore: Update translations --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Zafar Saeed Khan <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mark Brockhoff <[email protected]> Co-authored-by: Arjita <[email protected]> Co-authored-by: Adrian Weiß <[email protected]> Co-authored-by: Copilot <[email protected]> Co-authored-by: JacquelineLehner <[email protected]> Co-authored-by: Klaus Boldt <[email protected]> Co-authored-by: Immad Abdul Jabbar <[email protected]>
* initial commit * add close modal handler * added isFileEditable() * added edit option for conversation assets * add tests * fixed getNode api call * bump @webapp/core * fix package.json * fixed package.json * fix package.json * address PR comments * fixed types
* fix: remove call from the call state when a user is left the group (#19790) * chore(deps-dev): bump rimraf from 6.1.0 to 6.1.2 in /server (#19791) Bumps [rimraf](https://github.com/isaacs/rimraf) from 6.1.0 to 6.1.2. - [Changelog](https://github.com/isaacs/rimraf/blob/main/CHANGELOG.md) - [Commits](isaacs/rimraf@v6.1.0...v6.1.2) --- updated-dependencies: - dependency-name: rimraf dependency-version: 6.1.2 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * refactor(WPB-21957): create fixture for creating teams + refactor edit tests with it (#19804) This is an attempt to resolve the race conditions happening when two users connect in a 1:1 for the first time starting the conversation as proteus but it's migrated to MLS automatically. This leads to a message sent during the migration being lost. Team members don't need to go through this step as they are aware of the spoken protocol of other members after login. * test(WPB-19966): write "Reply" regression tests (#19760) * test(TC-8038): add test for not replying to a ping * test(TC-8039): add test for not replying to timed messages * test(TC-2994): add test for quote in reply to vanish if source message is removed * test(TC-2996): add test for searching message * test(TC-2997): test for quote in reply to be truncated * test(TC-3002): reply to a picture * test(TC-3003): reply to an audio message * test(TC-3004): reply to video * test(TC-3005): reply to link * test(TC3006): reply to file * test(TC-3007): reply to reply * test(TC-3008): reply to link with text * test(TC-3011): Reply with timed message * test(TC-3013): test clicking the reply * test(TC-3014): test replying in a conversation I'm no longer part of * test(TC-3016): click on mention in reply opens user profile * fix: remove visibility check from sendMessage * test(TC-3009): add test case for replying to a location + util for sending location via testservice * refactor: replace createPagesForUser with new fixtures * refactor(test): use new fixtures for reply tests * refactor: remove no longer used PagePlugin withConversation * fix: accessibility improvements login(https://wearezeta.atlassian.net/browse/WPB-20819) (#19714) * fix: make password toggle button accessible and localised(WPB-21228) * fix: translate type * fix: Login - New view is not announced * fix: make back button accessible WPB-21466 * fix: make external link 2fa accessible(WPB-21279) * fix: password toggle button text alternative(WPB-21228) * fix: make verify account header focusable using screenkey and login subheading style adjustments * fix: add toggle password show/hide label * fix: address review comments * chore: bump core packages * fix: pipeline issues * fix: PR comments * fix: pipeline issues * chore(deps): bump @wireapp/core from 46.46.3 to 46.46.5 (#19793) Bumps [@wireapp/core](https://github.com/wireapp/wire-web-packages) from 46.46.3 to 46.46.5. - [Commits](https://github.com/wireapp/wire-web-packages/compare/@wireapp/[email protected]...@wireapp/[email protected]) --- updated-dependencies: - dependency-name: "@wireapp/core" dependency-version: 46.46.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump core-js from 3.46.0 to 3.47.0 (#19797) Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.46.0 to 3.47.0. - [Release notes](https://github.com/zloirock/core-js/releases) - [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md) - [Commits](https://github.com/zloirock/core-js/commits/v3.47.0/packages/core-js) --- updated-dependencies: - dependency-name: core-js dependency-version: 3.47.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump emoji-picker-react from 4.15.1 to 4.15.2 (#19802) Bumps [emoji-picker-react](https://github.com/ealush/emoji-picker-react) from 4.15.1 to 4.15.2. - [Release notes](https://github.com/ealush/emoji-picker-react/releases) - [Commits](https://github.com/ealush/emoji-picker-react/commits) --- updated-dependencies: - dependency-name: emoji-picker-react dependency-version: 4.15.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump html-webpack-plugin from 5.6.4 to 5.6.5 (#19800) Bumps [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) from 5.6.4 to 5.6.5. - [Release notes](https://github.com/jantimon/html-webpack-plugin/releases) - [Changelog](https://github.com/jantimon/html-webpack-plugin/blob/main/CHANGELOG.md) - [Commits](jantimon/html-webpack-plugin@v5.6.4...v5.6.5) --- updated-dependencies: - dependency-name: html-webpack-plugin dependency-version: 5.6.5 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump oidc-client-ts from 3.4.0 to 3.4.1 (#19801) Bumps [oidc-client-ts](https://github.com/authts/oidc-client-ts) from 3.4.0 to 3.4.1. - [Release notes](https://github.com/authts/oidc-client-ts/releases) - [Commits](authts/oidc-client-ts@v3.4.0...v3.4.1) --- updated-dependencies: - dependency-name: oidc-client-ts dependency-version: 3.4.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump webpack from 5.102.1 to 5.103.0 (#19796) Bumps [webpack](https://github.com/webpack/webpack) from 5.102.1 to 5.103.0. - [Release notes](https://github.com/webpack/webpack/releases) - [Commits](webpack/webpack@v5.102.1...v5.103.0) --- updated-dependencies: - dependency-name: webpack dependency-version: 5.103.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump workbox-webpack-plugin from 7.3.0 to 7.4.0 (#19799) Bumps [workbox-webpack-plugin](https://github.com/googlechrome/workbox) from 7.3.0 to 7.4.0. - [Release notes](https://github.com/googlechrome/workbox/releases) - [Commits](GoogleChrome/workbox@v7.3.0...v7.4.0) --- updated-dependencies: - dependency-name: workbox-webpack-plugin dependency-version: 7.4.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump stylelint from 16.25.0 to 16.26.0 (#19798) Bumps [stylelint](https://github.com/stylelint/stylelint) from 16.25.0 to 16.26.0. - [Release notes](https://github.com/stylelint/stylelint/releases) - [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md) - [Commits](stylelint/stylelint@16.25.0...16.26.0) --- updated-dependencies: - dependency-name: stylelint dependency-version: 16.26.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump baseline-browser-mapping from 2.8.28 to 2.8.31 (#19792) Bumps [baseline-browser-mapping](https://github.com/web-platform-dx/baseline-browser-mapping) from 2.8.28 to 2.8.31. - [Release notes](https://github.com/web-platform-dx/baseline-browser-mapping/releases) - [Commits](web-platform-dx/baseline-browser-mapping@v2.8.28...v2.8.31) --- updated-dependencies: - dependency-name: baseline-browser-mapping dependency-version: 2.8.31 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * test(WPB-19968): add tests for self deleting messages (#19805) * test(TC-657): add test for sending ephemeral text message in 1:1 * test(TC-658): add test for sending ephemeral text message in group * refactor: replace util sendTimedMessage with dedicated utils for enabling and disabling timed messages * test(TC-662): Verify timer is applied to all messages until turning it off in 1:1 * test(TC-664): Verify that message with previous timer are deleted on start-up when the timeout passed in 1:1 * refactor: overload createPage fixture to optionally accept a context to reuse * refactor: use team for tests using new fixture * test(TC-675): Verify the message is not deleted for users that didn't read the message * test(TC-3715): set global group conversation timer * refactor(reply-tests): remove unused createUser fixture * test(TC-3716): check current time is visible in details * fix(a11y): add disabled attribute to MessageTimerButton * test(TC-3718): check timed message button is disabled if timed messages are set globally * test(TC-3719): globally set timer is shown on button next to input field * test(TC-3720): system messages are shown for enabled / disabled timer messages * test(TC-3717): check ephemeral message appear in search results * test(TC-3731): add test for message to disappear from search results (currently broken) * refactor: group search tests * refactor: update search result tests to do assertions on receiver side * refactor: group tests with self deleting messages set globally for a group conversation * docs: add ticket number to comment for skipped test * fix: prevent microphone disabled dialog display when muted (#19808) * test(WPB-21957): update backend endpoint to match api version (#19809) * chore: bump avs to v10.2.19 (#19810) * chore(deps): bump pm2 from 6.0.13 to 6.0.14 in /server (#19814) Bumps [pm2](https://github.com/Unitech/pm2) from 6.0.13 to 6.0.14. - [Release notes](https://github.com/Unitech/pm2/releases) - [Changelog](https://github.com/Unitech/pm2/blob/master/CHANGELOG.md) - [Commits](Unitech/pm2@v6.0.13...v6.0.14) --- updated-dependencies: - dependency-name: pm2 dependency-version: 6.0.14 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump js-yaml from 3.14.1 to 3.14.2 in /server (#19817) Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 3.14.1 to 3.14.2. - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](nodeca/js-yaml@3.14.1...3.14.2) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 3.14.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * test(WPB-19939): add authentication regression tests (#19826) * test(TC-34579: verify signin button is disabled inc ase of empty credentials * test(TC-3468): Verify sign in error appearance in case of suspended team account * test(TC-3460): Verify current browser is set as temporary device * test(TC-3465): Verify sign in error appearance in case of wrong credentials * test(TC-3472): Ensure history is kept after refresh on permanent device * test(TC-3473): create data driven test to also ensure history is kept on temporary device * test(TC-1311): verify session expires * test(TC-3480): check tls versions allowed by webapp server * test(TC-1311): Ensure history is gone after logging out of public computer * fix(websocket): optimise event handling. Add heartbeat [WPB-21950] (#19825) * fix(lifecycle): optimise online / offline event handling. Add heartbeat for WS * Update src/script/repositories/event/EventRepository.ts Co-authored-by: Copilot <[email protected]> * Update src/script/repositories/event/EventRepository.ts Co-authored-by: Copilot <[email protected]> * Update src/script/repositories/event/EventRepository.ts Co-authored-by: Copilot <[email protected]> * chore: rename to updateConnectivityStatus * chore: add copilot suggested improvements --------- Co-authored-by: Copilot <[email protected]> * chore(deps): bump express from 4.21.2 to 4.22.0 in /server (#19827) Bumps [express](https://github.com/expressjs/express) from 4.21.2 to 4.22.0. - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/4.22.0/History.md) - [Commits](expressjs/express@4.21.2...4.22.0) --- updated-dependencies: - dependency-name: express dependency-version: 4.22.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore: blocking user spec [19940] (#19784) * test(WPB-19940): add tests for blocking users * test(block): refactor block.spec.ts according to Review-Comments add function to userActions.ts to send a connection request add fixture for connection request delete conversationNotConnected.modal.ts, replace it with acknowledge.modal.ts * test(block): refactor block.spec.ts according to Review-Comments * test(block): refactor block.spec.ts according to Review-Comments * test(block): fixed unclear comments and variable namings --------- Co-authored-by: Klaus Boldt <[email protected]> * chore(deps): bump crowdin/github-action from 2.12.0 to 2.13.0 (#19828) Bumps [crowdin/github-action](https://github.com/crowdin/github-action) from 2.12.0 to 2.13.0. - [Release notes](https://github.com/crowdin/github-action/releases) - [Commits](crowdin/github-action@v2.12.0...v2.13.0) --- updated-dependencies: - dependency-name: crowdin/github-action dependency-version: 2.13.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat: integrate Collabora using iframe [WPB-21650] (#19813) * initial commit * add close modal handler * added isFileEditable() * added edit option for conversation assets * add tests * fixed getNode api call * bump @webapp/core * fix package.json * fixed package.json * fix package.json * address PR comments * fixed types * chore(deps-dev): bump stylelint from 16.26.0 to 16.26.1 (#19820) Bumps [stylelint](https://github.com/stylelint/stylelint) from 16.26.0 to 16.26.1. - [Release notes](https://github.com/stylelint/stylelint/releases) - [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md) - [Commits](stylelint/stylelint@16.26.0...16.26.1) --- updated-dependencies: - dependency-name: stylelint dependency-version: 16.26.1 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @playwright/test from 1.56.1 to 1.57.0 (#19818) Bumps [@playwright/test](https://github.com/microsoft/playwright) from 1.56.1 to 1.57.0. - [Release notes](https://github.com/microsoft/playwright/releases) - [Commits](microsoft/playwright@v1.56.1...v1.57.0) --- updated-dependencies: - dependency-name: "@playwright/test" dependency-version: 1.57.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump baseline-browser-mapping from 2.8.31 to 2.8.32 (#19819) Bumps [baseline-browser-mapping](https://github.com/web-platform-dx/baseline-browser-mapping) from 2.8.31 to 2.8.32. - [Release notes](https://github.com/web-platform-dx/baseline-browser-mapping/releases) - [Commits](web-platform-dx/baseline-browser-mapping@v2.8.31...v2.8.32) --- updated-dependencies: - dependency-name: baseline-browser-mapping dependency-version: 2.8.32 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump emoji-picker-react from 4.15.2 to 4.16.1 (#19822) Bumps [emoji-picker-react](https://github.com/ealush/emoji-picker-react) from 4.15.2 to 4.16.1. - [Release notes](https://github.com/ealush/emoji-picker-react/releases) - [Commits](https://github.com/ealush/emoji-picker-react/commits) --- updated-dependencies: - dependency-name: emoji-picker-react dependency-version: 4.16.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ci(WPB-21987): shard playwright tests across multiple runners (#19807) * refactor: use nvmrc to select node version * feat: add job to build test service * feat: shard tests across multiple runners with integrated testservice & job to collect reports * fix: build shadowJar of testservice * fix: generate json report when merging blobs * refactor: only download chrome browser for tests * ci: use github reporter in CI * fix: re-use playwright config when merging reports to generate json report for PR comment * refactor: don't pass github user and token when building testservice * feat: use 16 runners for sharding * feat: execute regression tests in addition to critical flow * fix: make script for reporting playwright summary work with nested test suites * chore: use SHA for third party actions (So Sonar shuts up) * refactor: use line reporter instead of github The report annotations are too annoying * refactor: stop background process of testservice after test * fix: run critical flow and regression tests * ci: increase number of parallel test runners to 32 Now that the regression tests and critical flow tests are executed 16 runners is a bit too little * style: ignore prettier for shard definition * chore: safe guard stripAnsi function in report generation * ci(WPB-21987): group test in playwright comment by file (#19830) * refactor: update report script to group tests by file * style: use list to render test cases * feat: add direct link to download playwright report * test(WPB-19966): fix getMessage locator to account for different message states (#19832) * chore: add env var MAX_API_VERSION [WPB-22159] (#19831) * runfix(cells): disable spammy tracking (#19829) * test(WPB-19968): use a unique test message to avoid strict mode violation (#19834) * test(WPB-19939): wait for login to finish before continuing (#19833) * chore: Update translations --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Zafar Saeed Khan <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mark Brockhoff <[email protected]> Co-authored-by: Arjita <[email protected]> Co-authored-by: Adrian Weiß <[email protected]> Co-authored-by: Copilot <[email protected]> Co-authored-by: JacquelineLehner <[email protected]> Co-authored-by: Klaus Boldt <[email protected]> Co-authored-by: Immad Abdul Jabbar <[email protected]>



Pull Request
Summary
We have to provide users a feature where they can collaborate on files. Like real time editing as a team.
With Collabora integration, we can allow user to achieve it.
Security Checklist (required)
Standards Acknowledgement (required)
Screenshots or demo (if the user interface changed)
Notes for reviewers
Screen.Recording.2025-11-28.at.16.07.26.mov
We are using
<iframe>to render the URL as we don't have native integration for Collabora.