diff --git a/src/components/ChannelList/__tests__/ChannelList.test.tsx b/src/components/ChannelList/__tests__/ChannelList.test.tsx
index e22d5d7cf..f2ff7579d 100644
--- a/src/components/ChannelList/__tests__/ChannelList.test.tsx
+++ b/src/components/ChannelList/__tests__/ChannelList.test.tsx
@@ -314,6 +314,42 @@ describe('ChannelList', () => {
expect(results).toHaveNoViolations();
});
+ it('should add a notification when the first page of channels fails to load', async () => {
+ useMockedApis(chatClient, [erroredPostApi()]);
+ const addNotificationSpy = vi.spyOn(chatClient.notifications, 'add');
+ vi.spyOn(console, 'warn').mockImplementation(() => null);
+
+ render(
+
+
+
+
+ ,
+ );
+
+ await waitFor(() => {
+ expect(addNotificationSpy).toHaveBeenCalledWith(
+ expect.objectContaining({
+ message: 'Failed to load channels',
+ options: expect.objectContaining({
+ severity: 'error',
+ tags: expect.arrayContaining(['target:channel-list']),
+ type: 'api:channel-list:load:failed',
+ }),
+ origin: { emitter: 'ChannelList' },
+ }),
+ );
+ });
+ });
+
it('provides the error object to LoadingErrorIndicator', async () => {
useMockedApis(chatClient, [erroredPostApi()]);
vi.spyOn(console, 'warn').mockImplementationOnce(() => null);
@@ -341,6 +377,54 @@ describe('ChannelList', () => {
expect(screen.getByText('StreamChat error HTTP code: 500')).toBeInTheDocument();
});
+ it('should keep loaded channels visible and add a notification when loading more fails', async () => {
+ useMockedApis(chatClient, [queryChannelsApi([testChannel1, testChannel2])]);
+ const addNotificationSpy = vi.spyOn(chatClient.notifications, 'add');
+ vi.spyOn(console, 'warn').mockImplementation(() => null);
+
+ render(
+
+
+
+
+ ,
+ );
+
+ await waitFor(() => {
+ expect(screen.getByTestId(testChannel1.channel.id)).toBeInTheDocument();
+ expect(screen.getByTestId(testChannel2.channel.id)).toBeInTheDocument();
+ });
+
+ useMockedApis(chatClient, [erroredPostApi()]);
+
+ await act(() => {
+ fireEvent.click(screen.getByTestId('load-more-button'));
+ });
+
+ await waitFor(() => {
+ expect(addNotificationSpy).toHaveBeenCalledWith(
+ expect.objectContaining({
+ message: 'Failed to load more channels',
+ options: expect.objectContaining({
+ severity: 'error',
+ tags: expect.arrayContaining(['target:channel-list']),
+ type: 'api:channel-list:load-more:failed',
+ }),
+ origin: { emitter: 'ChannelList' },
+ }),
+ );
+ });
+
+ expect(screen.getByTestId(testChannel1.channel.id)).toBeInTheDocument();
+ expect(screen.getByTestId(testChannel2.channel.id)).toBeInTheDocument();
+ expect(screen.queryByTestId('error-indicator')).not.toBeInTheDocument();
+ });
+
it('should render loading indicator before the first channel list load and on reload', async () => {
const channelsQueryStatesHistory = [];
const channelListMessengerLoadingHistory = [];
diff --git a/src/components/ChannelList/hooks/usePaginatedChannels.ts b/src/components/ChannelList/hooks/usePaginatedChannels.ts
index 3dfa592c5..86073e7c2 100644
--- a/src/components/ChannelList/hooks/usePaginatedChannels.ts
+++ b/src/components/ChannelList/hooks/usePaginatedChannels.ts
@@ -12,6 +12,8 @@ import type {
} from 'stream-chat';
import { useChatContext } from '../../../context/ChatContext';
+import { useTranslationContext } from '../../../context/TranslationContext';
+import { useNotificationApi } from '../../Notifications';
import type { ChannelsQueryState } from '../../Chat/hooks/useChannelsQueryState';
@@ -44,9 +46,11 @@ export const usePaginatedChannels = (
recoveryThrottleIntervalMs: number = RECOVER_LOADED_CHANNELS_THROTTLE_INTERVAL_IN_MS,
customQueryChannels?: CustomQueryChannelsFn,
) => {
+ const { addNotification } = useNotificationApi();
const {
channelsQueryState: { error, setError, setQueryInProgress },
} = useChatContext('usePaginatedChannels');
+ const { t } = useTranslationContext();
const [channels, setChannels] = useState>([]);
const [hasNextPage, setHasNextPage] = useState(true);
const lastRecoveryTimestamp = useRef(undefined);
@@ -62,6 +66,8 @@ export const usePaginatedChannels = (
// eslint-disable-next-line react-hooks/exhaustive-deps
const queryChannels = async (queryType = 'load-more') => {
setError(null);
+ const offset = queryType === 'reload' ? 0 : channels.length;
+ const isFirstPage = offset === 0;
if (queryType === 'reload') {
setChannels([]);
@@ -77,8 +83,6 @@ export const usePaginatedChannels = (
setHasNextPage,
});
} else {
- const offset = queryType === 'reload' ? 0 : channels.length;
-
const newOptions = {
offset,
...options,
@@ -105,7 +109,22 @@ export const usePaginatedChannels = (
}
} catch (error) {
console.warn(error);
- setError(error as ErrorFromResponse);
+ addNotification({
+ emitter: 'ChannelList',
+ error: error instanceof Error ? error : undefined,
+ message: isFirstPage
+ ? t('Failed to load channels')
+ : t('Failed to load more channels'),
+ severity: 'error',
+ targetPanels: ['channel-list'],
+ type: isFirstPage
+ ? 'api:channel-list:load:failed'
+ : 'api:channel-list:load-more:failed',
+ });
+
+ if (isFirstPage) {
+ setError(error as ErrorFromResponse);
+ }
}
setQueryInProgress(null);
diff --git a/src/i18n/de.json b/src/i18n/de.json
index 2103fe44f..b7fd83e70 100644
--- a/src/i18n/de.json
+++ b/src/i18n/de.json
@@ -96,10 +96,10 @@
"aria/Mark Message Unread": "Als ungelesen markieren",
"aria/Mark messages as read": "Nachrichten als gelesen markieren",
"aria/Menu": "Menü",
- "aria/Message,": "Nachricht,",
"aria/Message Actions": "Nachrichtenaktionen",
"aria/Message from {{ user }},": "Nachricht von {{ user }},",
"aria/Message Options": "Nachrichtenoptionen",
+ "aria/Message,": "Nachricht,",
"aria/Mute User": "Benutzer stummschalten",
"aria/Notifications": "Benachrichtigungen",
"aria/Open Attachment Selector": "Anhang-Auswahl öffnen",
@@ -229,6 +229,8 @@
"Failed to end the poll due to {{reason}}": "Umfrage konnte aufgrund von {{reason}} nicht beendet werden",
"Failed to jump to the first unread message": "Fehler beim Springen zur ersten ungelesenen Nachricht",
"Failed to leave channel": "Kanal konnte nicht verlassen werden",
+ "Failed to load channels": "Kanäle konnten nicht geladen werden",
+ "Failed to load more channels": "Weitere Kanäle konnten nicht geladen werden",
"Failed to mark channel as read": "Fehler beim Markieren des Kanals als gelesen",
"Failed to play the recording": "Wiedergabe der Aufnahme fehlgeschlagen",
"Failed to retrieve location": "Standort konnte nicht abgerufen werden",
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 5ceae9c9f..3d1e3b0d3 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -96,10 +96,10 @@
"aria/Mark Message Unread": "Mark Message Unread",
"aria/Mark messages as read": "Mark messages as read",
"aria/Menu": "Menu",
- "aria/Message,": "Message,",
"aria/Message Actions": "Message Actions",
"aria/Message from {{ user }},": "Message from {{ user }},",
"aria/Message Options": "Message Options",
+ "aria/Message,": "Message,",
"aria/Mute User": "Mute User",
"aria/Notifications": "Notifications",
"aria/Open Attachment Selector": "Open Attachment Selector",
@@ -229,6 +229,8 @@
"Failed to end the poll due to {{reason}}": "Failed to end the poll due to {{reason}}",
"Failed to jump to the first unread message": "Failed to jump to the first unread message",
"Failed to leave channel": "Failed to leave channel",
+ "Failed to load channels": "Failed to load channels",
+ "Failed to load more channels": "Failed to load more channels",
"Failed to mark channel as read": "Failed to mark channel as read",
"Failed to play the recording": "Failed to play the recording",
"Failed to retrieve location": "Failed to retrieve location",
diff --git a/src/i18n/es.json b/src/i18n/es.json
index c676e9a37..566ac477e 100644
--- a/src/i18n/es.json
+++ b/src/i18n/es.json
@@ -104,10 +104,10 @@
"aria/Mark Message Unread": "Marcar como no leído",
"aria/Mark messages as read": "Marcar mensajes como leídos",
"aria/Menu": "Menú",
- "aria/Message,": "Mensaje,",
"aria/Message Actions": "Acciones del mensaje",
"aria/Message from {{ user }},": "Mensaje de {{ user }},",
"aria/Message Options": "Opciones de mensaje",
+ "aria/Message,": "Mensaje,",
"aria/Mute User": "Silenciar usuario",
"aria/Notifications": "Notificaciones",
"aria/Open Attachment Selector": "Abrir selector de adjuntos",
@@ -237,6 +237,8 @@
"Failed to end the poll due to {{reason}}": "No se pudo terminar la encuesta debido a {{reason}}",
"Failed to jump to the first unread message": "Error al saltar al primer mensaje no leído",
"Failed to leave channel": "No se pudo salir del canal",
+ "Failed to load channels": "No se pudieron cargar los canales",
+ "Failed to load more channels": "No se pudieron cargar más canales",
"Failed to mark channel as read": "Error al marcar el canal como leído",
"Failed to play the recording": "No se pudo reproducir la grabación",
"Failed to retrieve location": "No se pudo obtener la ubicación",
diff --git a/src/i18n/fr.json b/src/i18n/fr.json
index bc3054f71..2b3d13b7d 100644
--- a/src/i18n/fr.json
+++ b/src/i18n/fr.json
@@ -104,10 +104,10 @@
"aria/Mark Message Unread": "Marquer comme non lu",
"aria/Mark messages as read": "Marquer les messages comme lus",
"aria/Menu": "Menu",
- "aria/Message,": "Message,",
"aria/Message Actions": "Actions du message",
"aria/Message from {{ user }},": "Message de {{ user }},",
"aria/Message Options": "Options du message",
+ "aria/Message,": "Message,",
"aria/Mute User": "Mettre en sourdine",
"aria/Notifications": "Notifications",
"aria/Open Attachment Selector": "Ouvrir le sélecteur de pièces jointes",
@@ -237,6 +237,8 @@
"Failed to end the poll due to {{reason}}": "Impossible de terminer le sondage en raison de {{reason}}",
"Failed to jump to the first unread message": "Échec du saut vers le premier message non lu",
"Failed to leave channel": "Impossible de quitter le canal",
+ "Failed to load channels": "Impossible de charger les canaux",
+ "Failed to load more channels": "Impossible de charger davantage de canaux",
"Failed to mark channel as read": "Échec du marquage du canal comme lu",
"Failed to play the recording": "Impossible de lire l'enregistrement",
"Failed to retrieve location": "Impossible de récupérer l'emplacement",
diff --git a/src/i18n/hi.json b/src/i18n/hi.json
index ca0ce2dc3..194f35c75 100644
--- a/src/i18n/hi.json
+++ b/src/i18n/hi.json
@@ -96,10 +96,10 @@
"aria/Mark Message Unread": "अपठित चिह्नित करें",
"aria/Mark messages as read": "संदेशों को पढ़ा हुआ चिह्नित करें",
"aria/Menu": "मेन्यू",
- "aria/Message,": "संदेश,",
"aria/Message Actions": "संदेश कार्रवाइयाँ",
"aria/Message from {{ user }},": "{{ user }} का संदेश,",
"aria/Message Options": "संदेश विकल्प",
+ "aria/Message,": "संदेश,",
"aria/Mute User": "उपयोगकर्ता म्यूट करें",
"aria/Notifications": "सूचनाएं",
"aria/Open Attachment Selector": "अटैचमेंट चयनकर्ता खोलें",
@@ -230,6 +230,8 @@
"Failed to end the poll due to {{reason}}": "{{reason}} के कारण पोल समाप्त करने में विफल",
"Failed to jump to the first unread message": "पहले अपठित संदेश पर जाने में विफल",
"Failed to leave channel": "चैनल छोड़ने में विफल",
+ "Failed to load channels": "चैनल लोड करने में विफल",
+ "Failed to load more channels": "और चैनल लोड करने में विफल",
"Failed to mark channel as read": "चैनल को पढ़ा हुआ चिह्नित करने में विफल।",
"Failed to play the recording": "रेकॉर्डिंग प्ले करने में विफल",
"Failed to retrieve location": "स्थान प्राप्त करने में विफल",
diff --git a/src/i18n/it.json b/src/i18n/it.json
index 4d73d13b9..e0946a230 100644
--- a/src/i18n/it.json
+++ b/src/i18n/it.json
@@ -104,10 +104,10 @@
"aria/Mark Message Unread": "Contrassegna come non letto",
"aria/Mark messages as read": "Segna i messaggi come letti",
"aria/Menu": "Menu",
- "aria/Message,": "Messaggio,",
"aria/Message Actions": "Azioni del messaggio",
"aria/Message from {{ user }},": "Messaggio di {{ user }},",
"aria/Message Options": "Opzioni di messaggio",
+ "aria/Message,": "Messaggio,",
"aria/Mute User": "Mute utente",
"aria/Notifications": "Notifiche",
"aria/Open Attachment Selector": "Apri selettore allegati",
@@ -237,6 +237,8 @@
"Failed to end the poll due to {{reason}}": "Impossibile terminare il sondaggio a causa di {{reason}}",
"Failed to jump to the first unread message": "Impossibile passare al primo messaggio non letto",
"Failed to leave channel": "Impossibile lasciare il canale",
+ "Failed to load channels": "Impossibile caricare i canali",
+ "Failed to load more channels": "Impossibile caricare altri canali",
"Failed to mark channel as read": "Impossibile contrassegnare il canale come letto",
"Failed to play the recording": "Impossibile riprodurre la registrazione",
"Failed to retrieve location": "Impossibile recuperare la posizione",
diff --git a/src/i18n/ja.json b/src/i18n/ja.json
index ba0e86060..c4c95114b 100644
--- a/src/i18n/ja.json
+++ b/src/i18n/ja.json
@@ -95,10 +95,10 @@
"aria/Mark Message Unread": "未読としてマーク",
"aria/Mark messages as read": "メッセージを既読にする",
"aria/Menu": "メニュー",
- "aria/Message,": "メッセージ,",
"aria/Message Actions": "メッセージ操作",
"aria/Message from {{ user }},": "{{ user }}さんからのメッセージ,",
"aria/Message Options": "メッセージオプション",
+ "aria/Message,": "メッセージ,",
"aria/Mute User": "ユーザーをミュート",
"aria/Notifications": "通知",
"aria/Open Attachment Selector": "添付ファイル選択を開く",
@@ -228,6 +228,8 @@
"Failed to end the poll due to {{reason}}": "{{reason}}のためアンケートの終了に失敗しました",
"Failed to jump to the first unread message": "最初の未読メッセージにジャンプできませんでした",
"Failed to leave channel": "チャンネルの退出に失敗しました",
+ "Failed to load channels": "チャンネルの読み込みに失敗しました",
+ "Failed to load more channels": "さらにチャンネルを読み込めませんでした",
"Failed to mark channel as read": "チャンネルを既読にすることができませんでした",
"Failed to play the recording": "録音の再生に失敗しました",
"Failed to retrieve location": "位置情報の取得に失敗しました",
diff --git a/src/i18n/ko.json b/src/i18n/ko.json
index ee5251c02..e62f03676 100644
--- a/src/i18n/ko.json
+++ b/src/i18n/ko.json
@@ -95,10 +95,10 @@
"aria/Mark Message Unread": "읽지 않음으로 표시",
"aria/Mark messages as read": "메시지를 읽음으로 표시",
"aria/Menu": "메뉴",
- "aria/Message,": "메시지,",
"aria/Message Actions": "메시지 작업",
"aria/Message from {{ user }},": "{{ user }}의 메시지,",
"aria/Message Options": "메시지 옵션",
+ "aria/Message,": "메시지,",
"aria/Mute User": "사용자 음소거",
"aria/Notifications": "알림",
"aria/Open Attachment Selector": "첨부 파일 선택기 열기",
@@ -228,6 +228,8 @@
"Failed to end the poll due to {{reason}}": "{{reason}}(으)로 인해 투표 종료에 실패했습니다",
"Failed to jump to the first unread message": "첫 번째 읽지 않은 메시지로 이동하지 못했습니다",
"Failed to leave channel": "채널 나가기에 실패했습니다",
+ "Failed to load channels": "채널을 불러오지 못했습니다",
+ "Failed to load more channels": "채널을 더 불러오지 못했습니다",
"Failed to mark channel as read": "채널을 읽음으로 표시하는 데 실패했습니다",
"Failed to play the recording": "녹음을 재생하지 못했습니다",
"Failed to retrieve location": "위치를 가져오지 못했습니다",
diff --git a/src/i18n/nl.json b/src/i18n/nl.json
index 4720d97e4..5d1b16af1 100644
--- a/src/i18n/nl.json
+++ b/src/i18n/nl.json
@@ -96,10 +96,10 @@
"aria/Mark Message Unread": "Markeren als ongelezen",
"aria/Mark messages as read": "Markeer berichten als gelezen",
"aria/Menu": "Menu",
- "aria/Message,": "Bericht,",
"aria/Message Actions": "Berichtacties",
"aria/Message from {{ user }},": "Bericht van {{ user }},",
"aria/Message Options": "Berichtopties",
+ "aria/Message,": "Bericht,",
"aria/Mute User": "Gebruiker dempen",
"aria/Notifications": "Meldingen",
"aria/Open Attachment Selector": "Open bijlage selector",
@@ -229,6 +229,8 @@
"Failed to end the poll due to {{reason}}": "Peiling kon niet worden beëindigd vanwege {{reason}}",
"Failed to jump to the first unread message": "Niet gelukt om naar het eerste ongelezen bericht te springen",
"Failed to leave channel": "Kanaal verlaten mislukt",
+ "Failed to load channels": "Kanalen konden niet worden geladen",
+ "Failed to load more channels": "Meer kanalen konden niet worden geladen",
"Failed to mark channel as read": "Kanaal kon niet als gelezen worden gemarkeerd",
"Failed to play the recording": "Kan de opname niet afspelen",
"Failed to retrieve location": "Locatie kon niet worden opgehaald",
diff --git a/src/i18n/pt.json b/src/i18n/pt.json
index a2aae6513..6b44bac3b 100644
--- a/src/i18n/pt.json
+++ b/src/i18n/pt.json
@@ -104,10 +104,10 @@
"aria/Mark Message Unread": "Marcar como não lida",
"aria/Mark messages as read": "Marcar mensagens como lidas",
"aria/Menu": "Menu",
- "aria/Message,": "Mensagem,",
"aria/Message Actions": "Ações da mensagem",
"aria/Message from {{ user }},": "Mensagem de {{ user }},",
"aria/Message Options": "Opções de mensagem",
+ "aria/Message,": "Mensagem,",
"aria/Mute User": "Silenciar usuário",
"aria/Notifications": "Notificações",
"aria/Open Attachment Selector": "Abrir seletor de anexos",
@@ -237,6 +237,8 @@
"Failed to end the poll due to {{reason}}": "Falha ao encerrar a enquete devido a {{reason}}",
"Failed to jump to the first unread message": "Falha ao pular para a primeira mensagem não lida",
"Failed to leave channel": "Falha ao sair do canal",
+ "Failed to load channels": "Falha ao carregar os canais",
+ "Failed to load more channels": "Falha ao carregar mais canais",
"Failed to mark channel as read": "Falha ao marcar o canal como lido",
"Failed to play the recording": "Falha ao reproduzir a gravação",
"Failed to retrieve location": "Falha ao obter localização",
diff --git a/src/i18n/ru.json b/src/i18n/ru.json
index 7adacc95d..830068fb9 100644
--- a/src/i18n/ru.json
+++ b/src/i18n/ru.json
@@ -113,10 +113,10 @@
"aria/Mark Message Unread": "Отметить как непрочитанное",
"aria/Mark messages as read": "Отметить сообщения как прочитанные",
"aria/Menu": "Меню",
- "aria/Message,": "Сообщение,",
"aria/Message Actions": "Действия с сообщением",
"aria/Message from {{ user }},": "Сообщение от {{ user }},",
"aria/Message Options": "Параметры сообщения",
+ "aria/Message,": "Сообщение,",
"aria/Mute User": "Отключить уведомления",
"aria/Notifications": "Уведомления",
"aria/Open Attachment Selector": "Открыть выбор вложений",
@@ -246,6 +246,8 @@
"Failed to end the poll due to {{reason}}": "Не удалось завершить опрос из-за {{reason}}",
"Failed to jump to the first unread message": "Не удалось перейти к первому непрочитанному сообщению",
"Failed to leave channel": "Не удалось покинуть канал",
+ "Failed to load channels": "Не удалось загрузить каналы",
+ "Failed to load more channels": "Не удалось загрузить больше каналов",
"Failed to mark channel as read": "Не удалось пометить канал как прочитанный",
"Failed to play the recording": "Не удалось воспроизвести запись",
"Failed to retrieve location": "Не удалось получить местоположение",
diff --git a/src/i18n/tr.json b/src/i18n/tr.json
index 3463969b0..42758610e 100644
--- a/src/i18n/tr.json
+++ b/src/i18n/tr.json
@@ -96,10 +96,10 @@
"aria/Mark Message Unread": "Okunmamış olarak işaretle",
"aria/Mark messages as read": "Mesajları okundu olarak işaretle",
"aria/Menu": "Menü",
- "aria/Message,": "Mesaj,",
"aria/Message Actions": "Mesaj eylemleri",
"aria/Message from {{ user }},": "{{ user }} adlı kullanıcıdan mesaj,",
"aria/Message Options": "Mesaj Seçenekleri",
+ "aria/Message,": "Mesaj,",
"aria/Mute User": "Kullanıcıyı sustur",
"aria/Notifications": "Bildirimler",
"aria/Open Attachment Selector": "Ek Seçiciyi Aç",
@@ -229,6 +229,8 @@
"Failed to end the poll due to {{reason}}": "{{reason}} nedeniyle anket sonlandırılamadı",
"Failed to jump to the first unread message": "İlk okunmamış mesaja atlamada hata oluştu",
"Failed to leave channel": "Kanaldan çıkılamadı",
+ "Failed to load channels": "Kanallar yüklenemedi",
+ "Failed to load more channels": "Daha fazla kanal yüklenemedi",
"Failed to mark channel as read": "Kanalı okundu olarak işaretleme başarısız oldu",
"Failed to play the recording": "Kayıt oynatılamadı",
"Failed to retrieve location": "Konum alınamadı",