diff --git a/apps/webapp/src/i18n/en-US.json b/apps/webapp/src/i18n/en-US.json
index f9319f97ba3..3b020706739 100644
--- a/apps/webapp/src/i18n/en-US.json
+++ b/apps/webapp/src/i18n/en-US.json
@@ -713,6 +713,13 @@
"conversationFileUploadOverlayDescription": "Drag & drop to add files",
"conversationFileUploadOverlayTitle": "Upload files",
"conversationFileVideoPreviewLabel": "Video file preview for: {src}",
+ "conversationFilterDrafts": "Drafts",
+ "conversationFilterMentions": "Mentions",
+ "conversationFilterNone": "No filter",
+ "conversationFilterPings": "Pings",
+ "conversationFilterReplies": "Replies",
+ "conversationFilterTooltip": "Filter conversations",
+ "conversationFilterUnread": "Unread",
"conversationFoldersEmptyText": "Add your conversations to folders to stay organized.",
"conversationFoldersEmptyTextLearnMore": "Learn more",
"conversationFooterArchive": "Archive",
@@ -1843,6 +1850,8 @@
"selfNotSupportMLSMsgPart1": "You can't communicate with {selfUserName}, as your device doesn't support the suitable protocol.",
"selfNotSupportMLSMsgPart2": "to call, and send messages and files.",
"selfProfileImageAlt": "Your profile picture",
+ "servicesNotEnabledNoteTitle": "Your team doesn't use apps yet",
+ "servicesNotEnabledBody": "To improve your workflow with apps, your team needs configuration. Please contact your team admin.",
"servicesOptionsTitle": "Apps",
"servicesRoomToggleInfo": "Open this conversation to apps.",
"servicesRoomToggleInfoExtended": "Open this conversation to apps. You can always change it later.",
diff --git a/apps/webapp/src/script/components/Modals/CreateConversation/CreateConversationSteps/Preference.tsx b/apps/webapp/src/script/components/Modals/CreateConversation/CreateConversationSteps/Preference.tsx
index b480d986535..1f4292411ce 100644
--- a/apps/webapp/src/script/components/Modals/CreateConversation/CreateConversationSteps/Preference.tsx
+++ b/apps/webapp/src/script/components/Modals/CreateConversation/CreateConversationSteps/Preference.tsx
@@ -20,6 +20,8 @@
import {CONVERSATION_PROTOCOL} from '@wireapp/api-client/lib/team';
import {container} from 'tsyringe';
+import {ConversationType} from 'Components/Modals/CreateConversation/types';
+import {AppsDisabledNote} from 'Components/Note/AppsDisabledNote/AppsDisabledNote';
import {InfoToggle} from 'Components/toggle/InfoToggle';
import {TeamState} from 'Repositories/team/TeamState';
import {Config} from 'src/script/Config';
@@ -27,7 +29,6 @@ import {useKoSubscribableChildren} from 'Util/ComponentUtil';
import {t} from 'Util/LocalizerUtil';
import {useCreateConversationModal} from '../hooks/useCreateConversationModal';
-import {ConversationType} from '../types';
export const Preference = () => {
const {
@@ -44,9 +45,16 @@ export const Preference = () => {
const teamState = container.resolve(TeamState);
- const {isCellsEnabled: isCellsEnabledForTeam, isMLSEnabled} = useKoSubscribableChildren(teamState, [
+ const {
+ isCellsEnabled: isCellsEnabledForTeam,
+ isMLSEnabled,
+ isAppsEnabled,
+ hasWhitelistedServices,
+ } = useKoSubscribableChildren(teamState, [
'isCellsEnabled',
'isMLSEnabled',
+ 'isAppsEnabled',
+ 'hasWhitelistedServices',
]);
const isCellsEnabledForEnvironment = Config.getConfig().FEATURE.ENABLE_CELLS;
const isCellsOptionEnabled = isCellsEnabledForEnvironment && isCellsEnabledForTeam;
@@ -55,7 +63,13 @@ export const Preference = () => {
? teamState.teamFeatures()?.mls?.config.defaultProtocol
: CONVERSATION_PROTOCOL.PROTEUS;
- // Read receipts are temorarily disabled for MLS groups and channels until it is supported
+ const isAppsFeatureAvailable =
+ (defaultProtocol === CONVERSATION_PROTOCOL.MLS && isAppsEnabled) ||
+ (defaultProtocol === CONVERSATION_PROTOCOL.PROTEUS &&
+ hasWhitelistedServices &&
+ conversationType !== ConversationType.Channel);
+
+ // Read receipts are temporarily disabled for MLS groups and channels until it is supported
const areReadReceiptsEnabled = defaultProtocol !== CONVERSATION_PROTOCOL.MLS;
return (
@@ -70,17 +84,17 @@ export const Preference = () => {
dataUieName="read-receipts"
/>
- {conversationType === ConversationType.Group && (
-
- )}
+ }
+ />
+
{areReadReceiptsEnabled && (
- {selectedProtocol.value !== CONVERSATION_PROTOCOL.MLS && (
-
- )}
+
+
+ {!isAppsFeatureAvailable && }
+
{areReadReceiptsEnabled && (
{
+ return (
+
+ {t('servicesNotEnabledBody')}
+
+ );
+};
+
+export {AppsDisabledNote};
diff --git a/apps/webapp/src/script/components/Note/Note.styles.ts b/apps/webapp/src/script/components/Note/Note.styles.ts
new file mode 100644
index 00000000000..7ded0083327
--- /dev/null
+++ b/apps/webapp/src/script/components/Note/Note.styles.ts
@@ -0,0 +1,49 @@
+/*
+ * Wire
+ * Copyright (C) 2026 Wire Swiss GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
+ *
+ */
+
+import {CSSObject} from '@emotion/react';
+
+export const ContainerStyle: CSSObject = {
+ display: 'flex',
+ flexDirection: 'column',
+ gap: '0.3rem',
+ padding: '0.75rem',
+ background: 'var(--accent-color-50)',
+ '.theme-dark &': {
+ background: 'var(--accent-color-800)',
+ boxShadow: 'none',
+ },
+ border: '1px solid var(--accent-color-500)',
+ borderRadius: '0.5rem',
+ lineHeight: '1.5',
+ marginTop: '0.3rem',
+};
+
+export const HeaderStyle: CSSObject = {
+ display: 'flex',
+ alignItems: 'center',
+ fontWeight: 'var(--font-weight-semibold)',
+ gap: '0.5rem',
+};
+
+export const ContentStyle: CSSObject = {
+ display: 'flex',
+ flexDirection: 'column',
+ gap: '4px',
+};
diff --git a/apps/webapp/src/script/components/Note/Note.tsx b/apps/webapp/src/script/components/Note/Note.tsx
new file mode 100644
index 00000000000..d3add20369a
--- /dev/null
+++ b/apps/webapp/src/script/components/Note/Note.tsx
@@ -0,0 +1,45 @@
+/*
+ * Wire
+ * Copyright (C) 2026 Wire Swiss GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
+ *
+ */
+
+import React, {ReactNode} from 'react';
+
+import {InfoIcon} from 'Components/Icon';
+import {ContainerStyle, ContentStyle, HeaderStyle} from 'Components/Note/Note.styles';
+
+interface NoteProps {
+ title: string;
+ children?: ReactNode;
+}
+
+const Note = ({title, children}: NoteProps) => {
+ return (
+
+ );
+};
+
+export {Note};
diff --git a/apps/webapp/src/script/components/toggle/InfoToggle.tsx b/apps/webapp/src/script/components/toggle/InfoToggle.tsx
index 9f831d4ef04..41265ec002a 100644
--- a/apps/webapp/src/script/components/toggle/InfoToggle.tsx
+++ b/apps/webapp/src/script/components/toggle/InfoToggle.tsx
@@ -17,7 +17,7 @@
*
*/
-import {useId} from 'react';
+import React, {useId} from 'react';
import cx from 'classnames';
@@ -29,6 +29,7 @@ interface InfoToggleProps {
name: string;
className?: string;
setIsChecked: (checked: boolean) => void;
+ label?: React.ReactNode;
}
const InfoToggle = ({
@@ -39,6 +40,7 @@ const InfoToggle = ({
isDisabled,
name,
setIsChecked,
+ label,
}: InfoToggleProps) => {
const dataUieNameInfoText = `status-info-toggle-${dataUieName}`;
const dataUieNameLabelText = `do-toggle-${dataUieName}`;
@@ -77,6 +79,7 @@ const InfoToggle = ({
+ {label}
);
};
diff --git a/apps/webapp/src/types/i18n.d.ts b/apps/webapp/src/types/i18n.d.ts
index 25a858c12dd..b6b94385073 100644
--- a/apps/webapp/src/types/i18n.d.ts
+++ b/apps/webapp/src/types/i18n.d.ts
@@ -1798,6 +1798,7 @@ declare module 'I18n/en-US.json' {
'searchCreateGroup': `Create group`;
'searchCreateGuestRoom': `Create guest room`;
'searchDirectConversations': `Search 1:1 conversations`;
+ 'searchDraftsConversations': `Search in drafts`;
'searchFavoriteConversations': `Search favorites`;
'searchFederatedDomainNotAvailable': `The federated domain is currently not available.`;
'searchFederatedDomainNotAvailableLearnMore': `Learn more`;
@@ -1816,6 +1817,7 @@ declare module 'I18n/en-US.json' {
'searchManageServices': `Manage Apps`;
'searchManageServicesNoResults': `Manage apps`;
'searchMemberInvite': `Invite people to join the team`;
+ 'searchMentionsConversations': `Search in mentions`;
'searchNoContactsOnWire': `You have no contacts on {brandName}.\nTry finding people by\nname or username.`;
'searchNoMatchesPartner': `No results`;
'searchNoServicesManager': `Apps are helpers that can improve your workflow.`;
@@ -1826,6 +1828,8 @@ declare module 'I18n/en-US.json' {
'searchPeople': `People`;
'searchPeopleOnlyPlaceholder': `Search people`;
'searchPeoplePlaceholder': `Search for people and conversations`;
+ 'searchPingsConversations': `Search in pings`;
+ 'searchRepliesConversations': `Search in replies`;
'searchServiceConfirmButton': `Open Conversation`;
'searchServicePlaceholder': `Search by name`;
'searchServices': `Apps`;
@@ -1835,6 +1839,7 @@ declare module 'I18n/en-US.json' {
'searchTrySearch': `Find people by\nname or username`;
'searchTrySearchFederation': `Find people in Wire by name or\n@username\n\nFind people from another domain\nby @username@domainname`;
'searchTrySearchLearnMore': `Learn more`;
+ 'searchUnreadConversations': `Search in unread`;
'selectAccountTypeHeading': `How will you use Wire?`;
'selectPersonalAccountTypeOptionButtonText': `Create Personal Account`;
'selectPersonalAccountTypeOptionDescription': `Chat with friends and family.`;
@@ -1849,6 +1854,8 @@ declare module 'I18n/en-US.json' {
'selfNotSupportMLSMsgPart1': `You can\'t communicate with {selfUserName}, as your device doesn\'t support the suitable protocol.`;
'selfNotSupportMLSMsgPart2': `to call, and send messages and files.`;
'selfProfileImageAlt': `Your profile picture`;
+ 'servicesNotEnabledNoteTitle': `Your team doesn\'t use apps yet`;
+ 'servicesNotEnabledBody': `To improve your workflow with apps, your team needs configuration. Please contact your team admin.`;
'servicesOptionsTitle': `Apps`;
'servicesRoomToggleInfo': `Open this conversation to apps.`;
'servicesRoomToggleInfoExtended': `Open this conversation to apps. You can always change it later.`;
@@ -1885,6 +1892,8 @@ declare module 'I18n/en-US.json' {
'success.openWebAppText': `Open Wire for web`;
'success.subheader': `What do you want to do next?`;
'systemMessageLearnMore': `Learn more`;
+ 'tabsFilterHeader': `Show filters`;
+ 'tabsFilterTooltip': `Customize visible tabs`;
'takeoverButtonChoose': `Choose your own`;
'takeoverButtonKeep': `Keep this one`;
'takeoverLink': `Learn more`;