diff --git a/app/assets/icons/arrow-upward.tsx b/app/assets/icons/arrow-upward.tsx
new file mode 100644
index 00000000..2d660c24
--- /dev/null
+++ b/app/assets/icons/arrow-upward.tsx
@@ -0,0 +1,12 @@
+import { Path } from 'react-native-svg';
+
+const ArrowUpwardOutlined = ({ color }: { color: string }) => (
+ <>
+
+ >
+);
+
+export default ArrowUpwardOutlined;
diff --git a/app/assets/icons/attach-file.tsx b/app/assets/icons/attach-file.tsx
new file mode 100644
index 00000000..3199cbd1
--- /dev/null
+++ b/app/assets/icons/attach-file.tsx
@@ -0,0 +1,12 @@
+import { Path } from 'react-native-svg';
+
+const AttachFileOutlined = ({ color }: { color: string }) => (
+ <>
+
+ >
+);
+
+export default AttachFileOutlined;
diff --git a/app/assets/icons/index.ts b/app/assets/icons/index.ts
index 37a0e84b..f03ab4d1 100644
--- a/app/assets/icons/index.ts
+++ b/app/assets/icons/index.ts
@@ -5,7 +5,9 @@ import AddBusinessOutlined from './add-business';
import AlternateEmailOutlined from './alternate-email';
import AltRouteOutlined from './alt-route';
import ApiOutlined from './api';
+import ArrowUpwardOutlined from './arrow-upward';
import AssignmentTurnedInOutlined from './assignment-turned-in';
+import AttachFileOutlined from './attach-file';
import BadgeOutlined from './badge';
import BalanceOutlined from './balance';
import CategoryOutlined from './category';
@@ -56,7 +58,9 @@ export const OutlinedIcons = {
'alternate-email': AlternateEmailOutlined,
'alt-route': AltRouteOutlined,
api: ApiOutlined,
+ 'arrow-upward': ArrowUpwardOutlined,
'assignment-turned-in': AssignmentTurnedInOutlined,
+ 'attach-file': AttachFileOutlined,
badge: BadgeOutlined,
balance: BalanceOutlined,
category: CategoryOutlined,
diff --git a/app/package-lock.json b/app/package-lock.json
index 17dbc2c3..592382a5 100644
--- a/app/package-lock.json
+++ b/app/package-lock.json
@@ -2044,6 +2044,7 @@
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz",
"integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==",
+ "dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -2055,6 +2056,7 @@
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz",
"integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==",
+ "dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -2065,6 +2067,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz",
"integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==",
+ "dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -5084,6 +5087,7 @@
"version": "0.2.12",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
"integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==",
+ "dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -5868,6 +5872,7 @@
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
"integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
+ "dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -6445,6 +6450,7 @@
"cpu": [
"arm"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6458,6 +6464,7 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6471,6 +6478,7 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6484,6 +6492,7 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6497,6 +6506,7 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6510,6 +6520,7 @@
"cpu": [
"arm"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6523,6 +6534,7 @@
"cpu": [
"arm"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6536,6 +6548,7 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6549,6 +6562,7 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6562,6 +6576,7 @@
"cpu": [
"ppc64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6575,6 +6590,7 @@
"cpu": [
"riscv64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6588,6 +6604,7 @@
"cpu": [
"riscv64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6601,6 +6618,7 @@
"cpu": [
"s390x"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6614,6 +6632,7 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6627,6 +6646,7 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6640,6 +6660,7 @@
"cpu": [
"wasm32"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
@@ -6656,6 +6677,7 @@
"cpu": [
"arm64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6669,6 +6691,7 @@
"cpu": [
"ia32"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -6682,6 +6705,7 @@
"cpu": [
"x64"
],
+ "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -7203,13 +7227,6 @@
}
}
},
- "node_modules/@wdio/reporter/node_modules/undici-types": {
- "version": "5.26.5",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
- "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@wdio/reporter/node_modules/typescript": {
"version": "4.9.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
@@ -7226,6 +7243,13 @@
"node": ">=4.2.0"
}
},
+ "node_modules/@wdio/reporter/node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@wdio/runner": {
"version": "9.24.0",
"resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-9.24.0.tgz",
diff --git a/app/src/__tests__/utils/formatting.test.ts b/app/src/__tests__/utils/formatting.test.ts
index 6d8b35a5..392051c6 100644
--- a/app/src/__tests__/utils/formatting.test.ts
+++ b/app/src/__tests__/utils/formatting.test.ts
@@ -11,6 +11,7 @@ import {
formatUtcDate,
calculateRelativeDate,
getDatePartsForLocale,
+ formatDateForChat,
} from '@/utils/formatting';
const EMPTY_STRING = '';
@@ -358,28 +359,24 @@ describe('getDatePartsForLocale', () => {
expect(getDatePartsForLocale('invalid-date', enLocale)).toBeNull();
});
- it('returns correct date and time parts for English locale', () => {
+ it('returns correct date parts for English locale', () => {
const result = getDatePartsForLocale(isoDate, enLocale);
expect(result).not.toBeNull();
if (!result) return;
- expect(result.hour).toBe('15');
- expect(result.minute).toBe('45');
expect(result.weekday).toBe('Tue');
expect(result.day).toBe('10');
expect(result.month).toBe('Mar');
expect(result.year).toBe('2026');
});
- it('returns correct date and time parts for French locale', () => {
+ it('returns correct date parts for French locale', () => {
const result = getDatePartsForLocale(isoDate, frLocale);
expect(result).not.toBeNull();
if (!result) return;
- expect(result.hour).toBe('15');
- expect(result.minute).toBe('45');
expect(result.weekday).toBe('mar.');
expect(result.day).toBe('10');
expect(result.month).toBe('mars');
@@ -393,11 +390,96 @@ describe('getDatePartsForLocale', () => {
expect(result).not.toBeNull();
if (!result) return;
- expect(result.hour).toBe('08');
- expect(result.minute).toBe('05');
expect(result.weekday).toBe('Fri');
expect(result.day).toBe('25');
expect(result.month).toBe('Dec');
expect(result.year).toBe('2026');
});
});
+
+describe('formatDateForChat', () => {
+ const locale = 'en-GB';
+
+ const NOW = new Date('2026-03-10T12:00:00Z');
+
+ beforeAll(() => {
+ jest.useFakeTimers();
+ jest.setSystemTime(NOW);
+ });
+
+ afterAll(() => {
+ jest.useRealTimers();
+ });
+
+ describe('invalid input', () => {
+ it('returns EMPTY_STRING when isoDate is undefined', () => {
+ expect(formatDateForChat(undefined, locale)).toBe(EMPTY_STRING);
+ });
+
+ it('returns EMPTY_STRING when isoDate is empty string', () => {
+ expect(formatDateForChat('', locale)).toBe(EMPTY_STRING);
+ });
+
+ it('returns EMPTY_STRING when isoDate is invalid', () => {
+ expect(formatDateForChat('invalid-date', locale)).toBe(EMPTY_STRING);
+ });
+ });
+
+ describe('within last 24 hours', () => {
+ it('returns time (HH:mm)', () => {
+ const iso = '2026-03-10T09:30:00Z';
+
+ expect(formatDateForChat(iso, locale)).toBe('09:30');
+ });
+ });
+
+ describe('within last 7 days', () => {
+ it('returns weekday', () => {
+ const iso = '2026-03-08T10:00:00Z';
+
+ const result = formatDateForChat(iso, locale);
+
+ expect(result).toBe('Sun');
+ });
+ });
+
+ describe('within current year but older than 7 days', () => {
+ it('returns DD Mon', () => {
+ const iso = '2026-02-01T10:00:00Z';
+
+ expect(formatDateForChat(iso, locale)).toBe('01 Feb');
+ });
+
+ it('pads day with leading zero', () => {
+ const iso = '2026-01-05T10:00:00Z';
+
+ expect(formatDateForChat(iso, locale)).toBe('05 Jan');
+ });
+ });
+
+ describe('older than current year', () => {
+ it('returns DD Mon YYYY', () => {
+ const iso = '2025-12-25T10:00:00Z';
+
+ expect(formatDateForChat(iso, locale)).toBe('25 Dec 2025');
+ });
+ });
+
+ describe('different locales', () => {
+ it('formats weekday using locale rules', () => {
+ const iso = '2026-03-08T10:00:00Z';
+
+ const result = formatDateForChat(iso, 'fr-FR');
+
+ expect(result).toBe('dim.');
+ });
+
+ it('formats month using locale rules', () => {
+ const iso = '2026-02-01T10:00:00Z';
+
+ const result = formatDateForChat(iso, 'fr-FR');
+
+ expect(result).toBe('01 févr.');
+ });
+ });
+});
diff --git a/app/src/components/avatar/Avatar.tsx b/app/src/components/avatar/Avatar.tsx
index 5486478e..dbb651fc 100644
--- a/app/src/components/avatar/Avatar.tsx
+++ b/app/src/components/avatar/Avatar.tsx
@@ -95,7 +95,7 @@ const Avatar: React.FC = ({
diff --git a/app/src/components/chat/ChatConversationFooter.tsx b/app/src/components/chat/ChatConversationFooter.tsx
new file mode 100644
index 00000000..ebb77703
--- /dev/null
+++ b/app/src/components/chat/ChatConversationFooter.tsx
@@ -0,0 +1,65 @@
+import { OutlinedIcons } from '@assets/icons';
+import { useTranslation } from 'react-i18next';
+import { View, TextInput, StyleSheet } from 'react-native';
+
+import OutlinedIcon from '@/components/common/OutlinedIcon';
+import { buttonStyle, Color, inputStyle, chatStyle } from '@/styles';
+
+type Props = {
+ value: string;
+ onChangeText: (text: string) => void;
+ onSend: () => void;
+};
+
+const ChatConversationFooter = ({ value, onChangeText, onSend }: Props) => {
+ const { t } = useTranslation();
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ textInputWrapper: chatStyle.textInputWrapper,
+ iconContainer: chatStyle.iconContainer,
+ inputContainer: chatStyle.inputContainer,
+ input: {
+ ...inputStyle.container,
+ ...inputStyle.inputChat,
+ },
+ buttonPrimaryIconOnly: {
+ ...buttonStyle.primary,
+ ...buttonStyle.primaryIconOnly,
+ },
+});
+
+export default ChatConversationFooter;
diff --git a/app/src/components/chat/ChatMessage.tsx b/app/src/components/chat/ChatMessage.tsx
new file mode 100644
index 00000000..e5144540
--- /dev/null
+++ b/app/src/components/chat/ChatMessage.tsx
@@ -0,0 +1,66 @@
+import { useMemo } from 'react';
+import { View, Text, StyleSheet } from 'react-native';
+
+import OutlinedIcon from '../common/OutlinedIcon';
+
+import Avatar from '@/components/avatar/Avatar';
+import { chatMessageStyle } from '@/styles/components';
+import { Color } from '@/styles/tokens';
+import type { Message, MessageType } from '@/types/chat';
+import { formatDateForChat, getTime } from '@/utils/formatting';
+
+type Props = {
+ message: Message;
+ currentUserId: string;
+ locale: string;
+};
+
+const ChatMessage = ({ message, currentUserId, locale }: Props) => {
+ const isOwn = message.identity.id === currentUserId;
+ const type: MessageType = isOwn ? 'own' : 'other';
+ const messageDate = formatDateForChat(message.audit.created?.at, locale);
+ const messageTime = getTime(message.audit.created?.at || '');
+
+ const styles = useMemo(
+ () =>
+ StyleSheet.create({
+ /* eslint-disable react-native/no-unused-styles */
+ container: chatMessageStyle[type].container,
+ messageWrapper: chatMessageStyle.messageWrapper,
+ textContainer: chatMessageStyle[type].textContainer,
+ text: chatMessageStyle[type].text,
+ info: chatMessageStyle[type].info,
+ infoText: chatMessageStyle.infoText,
+ avatarWrapper: chatMessageStyle.avatarWrapper,
+ }),
+ [type],
+ );
+
+ const avatarId = message.identity.id;
+ const avatarPath = message.identity?.icon;
+
+ return (
+
+ {!isOwn && (
+
+
+
+ )}
+
+
+ {!isOwn && {message.sender.identity.name}}
+ {messageDate !== messageTime && {messageDate}}
+ {messageTime}
+
+ {isOwn && }
+
+
+
+ {message.content}
+
+
+
+ );
+};
+
+export default ChatMessage;
diff --git a/app/src/components/details/DetailsHeader.tsx b/app/src/components/details/DetailsHeader.tsx
index 8b384604..9f3baa70 100644
--- a/app/src/components/details/DetailsHeader.tsx
+++ b/app/src/components/details/DetailsHeader.tsx
@@ -1,3 +1,4 @@
+import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { View, Text, StyleSheet } from 'react-native';
@@ -14,6 +15,7 @@ const DetailsHeader = ({
title,
subtitle,
statusText,
+ variant = 'default',
headerTitleTestId,
headerStatusTestId,
}: ListItemWithStatusProps) => {
@@ -23,6 +25,20 @@ const DetailsHeader = ({
const hasImage = Boolean(imagePath);
const status = getStatus(statusText, statusList);
+ const styles = useMemo(
+ () =>
+ StyleSheet.create({
+ /* eslint-disable react-native/no-unused-styles */
+ screenHeader: listItemStyle.detailsHeaderContainer[variant],
+ topRow: listItemStyle.detailsHeaderTopRow[variant],
+ avatarWrapper: listItemStyle.detailsHeaderAvatarWrapper[variant],
+ textWrapper: listItemStyle.textContainer,
+ title: listItemStyle.detailsHeaderTitle,
+ subtitle: listItemStyle.detailsHeaderSubtitle,
+ }),
+ [variant],
+ );
+
return (
@@ -42,20 +58,11 @@ const DetailsHeader = ({
- {status && (
+ {status && statusText && (
)}
);
};
-const styles = StyleSheet.create({
- screenHeader: listItemStyle.detailsHeaderContainer,
- topRow: listItemStyle.detailsHeaderTopRow,
- textWrapper: listItemStyle.textContainer,
- title: listItemStyle.detailsHeaderTitle,
- subtitle: listItemStyle.detailsHeaderSubtitle,
- avatarWrapper: listItemStyle.textAndImage.avatarWrapper,
-});
-
export default DetailsHeader;
diff --git a/app/src/i18n/en/chat.json b/app/src/i18n/en/chat.json
new file mode 100644
index 00000000..154b1065
--- /dev/null
+++ b/app/src/i18n/en/chat.json
@@ -0,0 +1,5 @@
+{
+ "chat": {
+ "messageInputPlaceholder": "Type a message"
+ }
+}
diff --git a/app/src/i18n/en/index.ts b/app/src/i18n/en/index.ts
index e90b1859..8f453792 100644
--- a/app/src/i18n/en/index.ts
+++ b/app/src/i18n/en/index.ts
@@ -3,6 +3,7 @@ import admin from './admin.json';
import auth from './auth.json';
import billing from './billing.json';
import catalog from './catalog.json';
+import chat from './chat.json';
import details from './details.json';
import home from './home.json';
import marketplace from './marketplace.json';
@@ -48,6 +49,9 @@ const en = {
// Module Administration (buyers, sellers)
...admin,
+
+ // Chat
+ ...chat,
};
export default en;
diff --git a/app/src/screens/account/UserSettingsScreen.tsx b/app/src/screens/account/UserSettingsScreen.tsx
index e041385e..48685d2b 100644
--- a/app/src/screens/account/UserSettingsScreen.tsx
+++ b/app/src/screens/account/UserSettingsScreen.tsx
@@ -73,7 +73,6 @@ const styles = StyleSheet.create({
},
sectionHeader: screenStyle.sectionHeader,
buttonPrimary: {
- ...buttonStyle.common,
...buttonStyle.primaryLight,
...buttonStyle.fullWidth,
},
diff --git a/app/src/screens/chat/ChatConversationScreen.tsx b/app/src/screens/chat/ChatConversationScreen.tsx
index a93debb9..d3812ce7 100644
--- a/app/src/screens/chat/ChatConversationScreen.tsx
+++ b/app/src/screens/chat/ChatConversationScreen.tsx
@@ -1,14 +1,62 @@
-import { RouteProp, useRoute } from '@react-navigation/native';
-import { Text } from 'react-native';
+import { useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { FlatList, KeyboardAvoidingView, Platform, StyleSheet } from 'react-native';
-import type { RootStackParamList } from '@/types/navigation';
+import { messages } from './messageData';
-type ChatConversationRouteProp = RouteProp;
+import ChatConversationFooter from '@/components/chat/ChatConversationFooter';
+import ChatMessage from '@/components/chat/ChatMessage';
+import DetailsHeader from '@/components/details/DetailsHeader';
+import { screenStyle } from '@/styles';
const ChatConversationScreen = () => {
- const { id } = useRoute().params;
+ const [inputText, setInputText] = useState('');
- return Chat for user {id};
+ // TODO: replace when API is ready
+ const currentUserId = 'USR-2267-7838';
+ const { i18n } = useTranslation();
+
+ const sendMessage = () => {
+ if (!inputText.trim()) return;
+ setInputText('');
+ };
+
+ return (
+
+ {/* TODO: replace with real data when API is ready */}
+
+ item.id}
+ keyboardShouldPersistTaps="handled"
+ renderItem={({ item }) => (
+
+ )}
+ />
+
+
+ );
};
+const styles = StyleSheet.create({
+ container: screenStyle.containerFlex,
+ flatList: {
+ ...screenStyle.containerFlex,
+ ...screenStyle.padding,
+ },
+});
+
export default ChatConversationScreen;
diff --git a/app/src/screens/chat/ChatScreen.tsx b/app/src/screens/chat/ChatScreen.tsx
index cbc9f469..9f12492e 100644
--- a/app/src/screens/chat/ChatScreen.tsx
+++ b/app/src/screens/chat/ChatScreen.tsx
@@ -1,13 +1,17 @@
import { useNavigation } from '@react-navigation/native';
import type { StackNavigationProp } from '@react-navigation/stack';
import { useEffect } from 'react';
-import { TouchableOpacity, Text } from 'react-native';
+import { data } from './chatData';
+
+import ListViewChat from '@/components/list/ListViewChat';
import { useSignalR } from '@/context/SignalRContext';
+import { ChatItem } from '@/types/chat';
import type { RootStackParamList } from '@/types/navigation';
const ChatScreen = () => {
const navigation = useNavigation>();
+
const { subscribe, unsubscribe, addMessageListener, isConnected } = useSignalR();
// TODO Subscribe to chat entities when connected here just for testing purposes, to be removed
@@ -37,18 +41,20 @@ const ChatScreen = () => {
return removeListener;
}, [addMessageListener]);
+ // TODO: warp into loading / error handling component when API is ready
return (
- {
+ {
navigation.navigate('chatConversation', {
- id: 'USR-123',
+ id,
});
}}
- activeOpacity={0.7}
- >
- USR: 123
- SignalR: {isConnected ? 'SignalR Connected' : 'SignalR Disconnected'}
-
+ />
);
};
diff --git a/app/src/screens/chat/chatData.ts b/app/src/screens/chat/chatData.ts
new file mode 100644
index 00000000..f8b90d3e
--- /dev/null
+++ b/app/src/screens/chat/chatData.ts
@@ -0,0 +1,901 @@
+export const data = [
+ {
+ id: 'CHT-0907-6973-2140',
+ name: 'Test Group - Vendor',
+ revision: 1,
+ type: 'Group',
+ participants: [
+ {
+ id: 'CHP-8745-6195-2902',
+ revision: 1,
+ chat: {
+ id: 'CHT-0907-6973-2140',
+ name: 'Test Group - Vendor',
+ revision: 1,
+ type: 'Group',
+ },
+ contact: {
+ id: 'CTT-0294-3021',
+ name: 'Darren Drumm',
+ revision: 1,
+ email: 'darren.drumm@softwareone.com',
+ identity: {
+ id: 'USR-7703-9615',
+ name: 'Darren Drumm',
+ revision: 3,
+ },
+ },
+ identity: {
+ id: 'USR-7703-9615',
+ name: 'Darren Drumm',
+ revision: 3,
+ },
+ account: {
+ id: 'ACC-4714-5418',
+ name: 'Microsoft',
+ revision: 1,
+ type: 'Vendor',
+ status: 'Active',
+ },
+ muted: false,
+ status: 'Active',
+ unreadMessageCount: 1,
+ },
+ {
+ id: 'CHP-9901-7302-2345',
+ revision: 3,
+ chat: {
+ id: 'CHT-0907-6973-2140',
+ name: 'Test Group - Vendor',
+ revision: 1,
+ type: 'Group',
+ },
+ contact: {
+ id: 'CTT-4262-4296',
+ name: 'Tania Roche',
+ revision: 1,
+ email: 'tania.roche@softwareone.com',
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ lastReadMessage: {
+ id: 'CMG-3801-3447-8769',
+ revision: 1,
+ content: 'a test message with very very very long text that needs to be truncated',
+ visibility: 'Public',
+ isDeleted: false,
+ },
+ unreadMessageCount: 1000,
+ },
+ ],
+ lastMessage: {
+ id: 'CMG-3801-3447-8769',
+ revision: 1,
+ chat: {
+ id: 'CHT-0907-6973-2140',
+ name: 'Test Group - Vendor',
+ revision: 1,
+ type: 'Group',
+ },
+ sender: {
+ id: 'CHP-9901-7302-2345',
+ revision: 3,
+ chat: {
+ id: 'CHT-0907-6973-2140',
+ name: 'Test Group - Vendor',
+ revision: 1,
+ type: 'Group',
+ },
+ contact: {
+ id: 'CTT-4262-4296',
+ name: 'Tania Roche',
+ revision: 1,
+ email: 'tania.roche@softwareone.com',
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ lastReadMessage: {
+ id: 'CMG-3801-3447-8769',
+ revision: 1,
+ content: 'a test message with very very very long text that needs to be truncated',
+ visibility: 'Public',
+ isDeleted: false,
+ },
+ unreadMessageCount: 0,
+ },
+ content: 'a test message with very very very long text that needs to be truncated',
+ visibility: 'Public',
+ isDeleted: false,
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ audit: {
+ deleted: {},
+ madePublic: {},
+ madePrivate: {},
+ created: {
+ at: '2026-03-10T13:10:37.212Z',
+ by: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ updated: {},
+ },
+ },
+ },
+ {
+ id: 'CHT-2749-6237-9222',
+ revision: 1,
+ type: 'Direct',
+ participants: [
+ {
+ id: 'CHP-1501-9758-7338',
+ revision: 1,
+ chat: {
+ id: 'CHT-2749-6237-9222',
+ revision: 1,
+ type: 'Direct',
+ },
+ contact: {
+ id: 'CTT-2736-2051',
+ name: 'microsoft licenses address',
+ revision: 1,
+ email: 'msft@medpt.com',
+ identity: {
+ id: 'USR-2421-6365',
+ name: 'microsoft licenses address',
+ revision: 1,
+ },
+ },
+ identity: {
+ id: 'USR-2421-6365',
+ name: 'microsoft licenses address',
+ revision: 1,
+ },
+ account: {
+ id: 'ACC-2180-7619',
+ name: 'Medpoint Digital, Inc.',
+ revision: 1,
+ type: 'Client',
+ status: 'Active',
+ },
+ muted: false,
+ status: 'Active',
+ unreadMessageCount: 1,
+ },
+ {
+ id: 'CHP-8024-2154-4959',
+ revision: 5,
+ chat: {
+ id: 'CHT-2749-6237-9222',
+ revision: 1,
+ type: 'Direct',
+ },
+ contact: {
+ id: 'CTT-4262-4296',
+ name: 'Tania Roche',
+ revision: 1,
+ email: 'tania.roche@softwareone.com',
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ lastReadMessage: {
+ id: 'CMG-6449-4326-9246',
+ revision: 1,
+ content: 'test',
+ visibility: 'Public',
+ isDeleted: false,
+ },
+ unreadMessageCount: 2,
+ },
+ ],
+ lastMessage: {
+ id: 'CMG-6449-4326-9246',
+ revision: 1,
+ chat: {
+ id: 'CHT-2749-6237-9222',
+ revision: 1,
+ type: 'Direct',
+ },
+ sender: {
+ id: 'CHP-8024-2154-4959',
+ revision: 5,
+ chat: {
+ id: 'CHT-2749-6237-9222',
+ revision: 1,
+ type: 'Direct',
+ },
+ contact: {
+ id: 'CTT-4262-4296',
+ name: 'Tania Roche',
+ revision: 1,
+ email: 'tania.roche@softwareone.com',
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ lastReadMessage: {
+ id: 'CMG-6449-4326-9246',
+ revision: 1,
+ content: 'test',
+ visibility: 'Public',
+ isDeleted: false,
+ },
+ unreadMessageCount: 0,
+ },
+ content: 'test',
+ visibility: 'Public',
+ isDeleted: false,
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ audit: {
+ deleted: {},
+ madePublic: {},
+ madePrivate: {},
+ created: {
+ at: '2026-03-09T12:54:25.055Z',
+ by: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ updated: {},
+ },
+ },
+ },
+ {
+ id: 'CHT-9231-8917-3633',
+ name: 'Mobile Dev Test Chat - Group One',
+ revision: 2,
+ type: 'Group',
+ participants: [
+ {
+ id: 'CHP-2317-4035-2836',
+ revision: 1,
+ chat: {
+ id: 'CHT-9231-8917-3633',
+ name: 'Mobile Dev Test Chat - Group One',
+ revision: 2,
+ type: 'Group',
+ },
+ contact: {
+ id: 'CTT-0869-8652',
+ name: 'Maciej Biernat',
+ revision: 1,
+ email: 'maciej.biernat@softwareone.com',
+ identity: {
+ id: 'USR-1835-2941',
+ name: 'Maciej Biernat',
+ icon: '/v1/accounts/users/USR-1835-2941/icon',
+ revision: 8,
+ },
+ },
+ identity: {
+ id: 'USR-1835-2941',
+ name: 'Maciej Biernat',
+ icon: '/v1/accounts/users/USR-1835-2941/icon',
+ revision: 8,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ unreadMessageCount: 6,
+ },
+ {
+ id: 'CHP-4483-3016-2902',
+ revision: 1,
+ chat: {
+ id: 'CHT-9231-8917-3633',
+ name: 'Mobile Dev Test Chat - Group One',
+ revision: 2,
+ type: 'Group',
+ },
+ contact: {
+ id: 'CTT-5259-9165',
+ name: 'Halil Karaca',
+ revision: 1,
+ email: 'halil.karaca@softwareone.com',
+ identity: {
+ id: 'USR-8314-3681',
+ name: 'Halil Karaca',
+ revision: 1,
+ },
+ },
+ identity: {
+ id: 'USR-8314-3681',
+ name: 'Halil Karaca',
+ revision: 1,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ unreadMessageCount: 6,
+ },
+ {
+ id: 'CHP-5307-6784-3140',
+ revision: 14,
+ chat: {
+ id: 'CHT-9231-8917-3633',
+ name: 'Mobile Dev Test Chat - Group One',
+ revision: 2,
+ type: 'Group',
+ },
+ contact: {
+ id: 'CTT-4262-4296',
+ name: 'Tania Roche',
+ revision: 1,
+ email: 'tania.roche@softwareone.com',
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ lastReadMessage: {
+ id: 'CMG-1083-9603-6187',
+ revision: 1,
+ content: 'test for recent message',
+ visibility: 'Public',
+ isDeleted: false,
+ },
+ unreadMessageCount: 0,
+ },
+ {
+ id: 'CHP-5576-4281-4209',
+ revision: 1,
+ chat: {
+ id: 'CHT-9231-8917-3633',
+ name: 'Mobile Dev Test Chat - Group One',
+ revision: 2,
+ type: 'Group',
+ },
+ contact: {
+ id: 'CTT-5591-7535',
+ name: 'Magdalena Komuda',
+ revision: 1,
+ email: 'Magdalena.Komuda@softwareone.com',
+ identity: {
+ id: 'USR-8905-2920',
+ name: 'Magdalena Komuda',
+ revision: 1,
+ },
+ },
+ identity: {
+ id: 'USR-8905-2920',
+ name: 'Magdalena Komuda',
+ revision: 1,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ unreadMessageCount: 6,
+ },
+ {
+ id: 'CHP-6078-8516-3871',
+ revision: 1,
+ chat: {
+ id: 'CHT-9231-8917-3633',
+ name: 'Mobile Dev Test Chat - Group One',
+ revision: 2,
+ type: 'Group',
+ },
+ contact: {
+ id: 'CTT-8104-3524',
+ name: 'Balint Polgar',
+ revision: 1,
+ email: 'balint.polgar@softwareone.com',
+ identity: {
+ id: 'USR-0556-8733',
+ name: 'Balint Polgar',
+ icon: '/v1/accounts/users/USR-0556-8733/icon',
+ revision: 18,
+ },
+ },
+ identity: {
+ id: 'USR-0556-8733',
+ name: 'Balint Polgar',
+ icon: '/v1/accounts/users/USR-0556-8733/icon',
+ revision: 18,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ unreadMessageCount: 6,
+ },
+ {
+ id: 'CHP-8092-8347-2652',
+ revision: 16,
+ chat: {
+ id: 'CHT-9231-8917-3633',
+ name: 'Mobile Dev Test Chat - Group One',
+ revision: 2,
+ type: 'Group',
+ },
+ contact: {
+ id: 'CTT-4634-2964',
+ name: 'MIchal Walczak',
+ revision: 1,
+ email: 'michal.walczak@softwareone.com',
+ identity: {
+ id: 'USR-2022-1452',
+ name: 'Michal Walczak',
+ icon: '/v1/accounts/users/USR-2022-1452/icon',
+ revision: 26,
+ },
+ },
+ identity: {
+ id: 'USR-2022-1452',
+ name: 'Michal Walczak',
+ icon: '/v1/accounts/users/USR-2022-1452/icon',
+ revision: 26,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ lastReadMessage: {
+ id: 'CMG-1083-9603-6187',
+ revision: 1,
+ content: 'test for recent message',
+ visibility: 'Public',
+ isDeleted: false,
+ },
+ unreadMessageCount: 0,
+ },
+ ],
+ lastMessage: {
+ id: 'CMG-1083-9603-6187',
+ revision: 1,
+ chat: {
+ id: 'CHT-9231-8917-3633',
+ name: 'Mobile Dev Test Chat - Group One',
+ revision: 2,
+ type: 'Group',
+ },
+ sender: {
+ id: 'CHP-5307-6784-3140',
+ revision: 14,
+ chat: {
+ id: 'CHT-9231-8917-3633',
+ name: 'Mobile Dev Test Chat - Group One',
+ revision: 2,
+ type: 'Group',
+ },
+ contact: {
+ id: 'CTT-4262-4296',
+ name: 'Tania Roche',
+ revision: 1,
+ email: 'tania.roche@softwareone.com',
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ lastReadMessage: {
+ id: 'CMG-1083-9603-6187',
+ revision: 1,
+ content: 'test for recent message',
+ visibility: 'Public',
+ isDeleted: false,
+ },
+ unreadMessageCount: 0,
+ },
+ content: 'test for recent message',
+ visibility: 'Public',
+ isDeleted: false,
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ audit: {
+ deleted: {},
+ madePublic: {},
+ madePrivate: {},
+ created: {
+ at: '2026-02-09T10:50:26.430Z',
+ by: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ updated: {},
+ },
+ },
+ },
+ {
+ id: 'CHT-4253-7222-5702',
+ revision: 1,
+ type: 'Direct',
+ participants: [
+ {
+ id: 'CHP-4768-7226-5802',
+ revision: 9,
+ chat: {
+ id: 'CHT-4253-7222-5702',
+ revision: 1,
+ type: 'Direct',
+ },
+ contact: {
+ id: 'CTT-4634-2964',
+ name: 'MIchal Walczak',
+ revision: 1,
+ email: 'michal.walczak@softwareone.com',
+ identity: {
+ id: 'USR-2022-1452',
+ name: 'Michal Walczak',
+ icon: '/v1/accounts/users/USR-2022-1452/icon',
+ revision: 26,
+ },
+ },
+ identity: {
+ id: 'USR-2022-1452',
+ name: 'Michal Walczak',
+ icon: '/v1/accounts/users/USR-2022-1452/icon',
+ revision: 26,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ lastReadMessage: {
+ id: 'CMG-4912-0427-1898',
+ revision: 1,
+ content: 'You should be able to see that chat, as I have invited you too',
+ visibility: 'Public',
+ isDeleted: false,
+ },
+ unreadMessageCount: 1,
+ },
+ {
+ id: 'CHP-6694-2147-1686',
+ revision: 17,
+ chat: {
+ id: 'CHT-4253-7222-5702',
+ revision: 1,
+ type: 'Direct',
+ },
+ contact: {
+ id: 'CTT-4262-4296',
+ name: 'Tania Roche',
+ revision: 1,
+ email: 'tania.roche@softwareone.com',
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ lastReadMessage: {
+ id: 'CMG-4348-8387-0436',
+ revision: 1,
+ content: 'update test',
+ visibility: 'Public',
+ isDeleted: false,
+ },
+ unreadMessageCount: 100,
+ },
+ ],
+ lastMessage: {
+ id: 'CMG-4348-8387-0436',
+ revision: 1,
+ chat: {
+ id: 'CHT-4253-7222-5702',
+ revision: 1,
+ type: 'Direct',
+ },
+ sender: {
+ id: 'CHP-6694-2147-1686',
+ revision: 17,
+ chat: {
+ id: 'CHT-4253-7222-5702',
+ revision: 1,
+ type: 'Direct',
+ },
+ contact: {
+ id: 'CTT-4262-4296',
+ name: 'Tania Roche',
+ revision: 1,
+ email: 'tania.roche@softwareone.com',
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ lastReadMessage: {
+ id: 'CMG-4348-8387-0436',
+ revision: 1,
+ content: 'update test',
+ visibility: 'Public',
+ isDeleted: false,
+ },
+ unreadMessageCount: 0,
+ },
+ content: 'update test',
+ visibility: 'Public',
+ isDeleted: false,
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ audit: {
+ deleted: {},
+ madePublic: {},
+ madePrivate: {},
+ created: {
+ at: '2025-03-09T10:46:50.968Z',
+ by: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ updated: {},
+ },
+ },
+ },
+ {
+ id: 'CHT-3390-6074-5983',
+ revision: 1,
+ type: 'Direct',
+ participants: [
+ {
+ id: 'CHP-1678-4601-5308',
+ revision: 1,
+ chat: {
+ id: 'CHT-3390-6074-5983',
+ revision: 1,
+ type: 'Direct',
+ },
+ contact: {
+ id: 'CTT-4262-4296',
+ name: 'Tania Roche',
+ revision: 1,
+ email: 'tania.roche@softwareone.com',
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ unreadMessageCount: 0,
+ },
+ {
+ id: 'CHP-5456-0462-7816',
+ revision: 1,
+ chat: {
+ id: 'CHT-3390-6074-5983',
+ revision: 1,
+ type: 'Direct',
+ },
+ contact: {
+ id: 'CTT-0869-8652',
+ name: 'Maciej Biernat',
+ revision: 1,
+ email: 'maciej.biernat@softwareone.com',
+ identity: {
+ id: 'USR-1835-2941',
+ name: 'Maciej Biernat',
+ icon: '/v1/accounts/users/USR-1835-2941/icon',
+ revision: 8,
+ },
+ },
+ identity: {
+ id: 'USR-1835-2941',
+ name: 'Maciej Biernat',
+ icon: '/v1/accounts/users/USR-1835-2941/icon',
+ revision: 8,
+ },
+ account: {
+ id: 'ACC-1360-4582',
+ name: 'Adastra',
+ icon: '/v1/accounts/accounts/ACC-1360-4582/icon',
+ revision: 1,
+ type: 'Client',
+ status: 'Active',
+ },
+ muted: false,
+ status: 'Active',
+ unreadMessageCount: 0,
+ },
+ ],
+ },
+];
diff --git a/app/src/screens/chat/messageData.ts b/app/src/screens/chat/messageData.ts
new file mode 100644
index 00000000..aee0bd88
--- /dev/null
+++ b/app/src/screens/chat/messageData.ts
@@ -0,0 +1,464 @@
+import type { Message } from '@/types/chat';
+
+export const messages: Message[] = [
+ {
+ id: 'CMG-4912-0427-1898',
+ revision: 1,
+ chat: {
+ id: 'CHT-4253-7222-5702',
+ revision: 1,
+ type: 'Direct',
+ },
+ sender: {
+ id: 'CHP-6694-2147-1686',
+ revision: 21,
+ chat: {
+ id: 'CHT-4253-7222-5702',
+ revision: 1,
+ type: 'Direct',
+ },
+ contact: {
+ id: 'CTT-4262-4296',
+ name: 'Tania Roche',
+ revision: 1,
+ email: 'tania.roche@softwareone.com',
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ lastReadMessage: {
+ id: 'CMG-4348-8387-0436',
+ revision: 1,
+ content: 'update test',
+ visibility: 'Public',
+ isDeleted: false,
+ },
+ unreadMessageCount: 0,
+ },
+ content: 'You should be able to see that chat, as I have invited you too',
+ visibility: 'Public',
+ isDeleted: false,
+ links: [],
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ audit: {
+ deleted: {},
+ madePublic: {},
+ madePrivate: {},
+ created: {
+ at: '2026-03-05T15:24:58.200Z',
+ by: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ updated: {},
+ },
+ },
+ {
+ id: 'CMG-2109-4320-3483',
+ revision: 1,
+ chat: {
+ id: 'CHT-4253-7222-5702',
+ revision: 1,
+ type: 'Direct',
+ },
+ sender: {
+ id: 'CHP-6694-2147-1686',
+ revision: 21,
+ chat: {
+ id: 'CHT-4253-7222-5702',
+ revision: 1,
+ type: 'Direct',
+ },
+ contact: {
+ id: 'CTT-4262-4296',
+ name: 'Tania Roche',
+ revision: 1,
+ email: 'tania.roche@softwareone.com',
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ lastReadMessage: {
+ id: 'CMG-4348-8387-0436',
+ revision: 1,
+ content: 'update test',
+ visibility: 'Public',
+ isDeleted: false,
+ },
+ unreadMessageCount: 0,
+ },
+ content: 'also, they are random avatars except the first one... ',
+ visibility: 'Public',
+ isDeleted: false,
+ links: [],
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ audit: {
+ deleted: {},
+ madePublic: {},
+ madePrivate: {},
+ created: {
+ at: '2026-03-05T15:24:41.616Z',
+ by: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ updated: {},
+ },
+ },
+ {
+ id: 'CMG-6293-5431-6796',
+ revision: 1,
+ chat: {
+ id: 'CHT-4253-7222-5702',
+ revision: 1,
+ type: 'Direct',
+ },
+ sender: {
+ id: 'CHP-6694-2147-1686',
+ revision: 21,
+ chat: {
+ id: 'CHT-4253-7222-5702',
+ revision: 1,
+ type: 'Direct',
+ },
+ contact: {
+ id: 'CTT-4262-4296',
+ name: 'Tania Roche',
+ revision: 1,
+ email: 'tania.roche@softwareone.com',
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ lastReadMessage: {
+ id: 'CMG-4348-8387-0436',
+ revision: 1,
+ content: 'update test',
+ visibility: 'Public',
+ isDeleted: false,
+ },
+ unreadMessageCount: 0,
+ },
+ content:
+ 'Just created group chat with 5+ users... and only seeing 3 avatars... hm... maybe bug',
+ visibility: 'Public',
+ isDeleted: false,
+ links: [],
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ audit: {
+ deleted: {},
+ madePublic: {},
+ madePrivate: {},
+ created: {
+ at: '2026-03-05T15:23:06.420Z',
+ by: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ updated: {},
+ },
+ },
+ {
+ id: 'CMG-7791-1345-9401',
+ revision: 1,
+ chat: {
+ id: 'CHT-4253-7222-5702',
+ revision: 1,
+ type: 'Direct',
+ },
+ sender: {
+ id: 'CHP-6694-2147-1686',
+ revision: 21,
+ chat: {
+ id: 'CHT-4253-7222-5702',
+ revision: 1,
+ type: 'Direct',
+ },
+ contact: {
+ id: 'CTT-4262-4296',
+ name: 'Tania Roche',
+ revision: 1,
+ email: 'tania.roche@softwareone.com',
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ lastReadMessage: {
+ id: 'CMG-4348-8387-0436',
+ revision: 1,
+ content: 'update test',
+ visibility: 'Public',
+ isDeleted: false,
+ },
+ unreadMessageCount: 0,
+ },
+ content: 'he he :) first message on our own SWO chat!',
+ visibility: 'Public',
+ isDeleted: false,
+ links: [],
+ identity: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ audit: {
+ deleted: {},
+ madePublic: {},
+ madePrivate: {},
+ created: {
+ at: '2026-03-05T15:22:29.602Z',
+ by: {
+ id: 'USR-2267-7838',
+ name: 'Tania Roche',
+ revision: 1,
+ },
+ },
+ updated: {},
+ },
+ },
+ {
+ id: 'CMG-3243-2050-3705',
+ revision: 1,
+ chat: {
+ id: 'CHT-4253-7222-5702',
+ revision: 1,
+ type: 'Direct',
+ },
+ sender: {
+ id: 'CHP-4768-7226-5802',
+ revision: 10,
+ chat: {
+ id: 'CHT-4253-7222-5702',
+ revision: 1,
+ type: 'Direct',
+ },
+ contact: {
+ id: 'CTT-4634-2964',
+ name: 'MIchal Walczak',
+ revision: 1,
+ email: 'michal.walczak@softwareone.com',
+ identity: {
+ id: 'USR-2022-1452',
+ name: 'Michal Walczak',
+ icon: '/v1/accounts/users/USR-2022-1452/icon',
+ revision: 26,
+ },
+ },
+ identity: {
+ id: 'USR-2022-1452',
+ name: 'Michal Walczak',
+ icon: '/v1/accounts/users/USR-2022-1452/icon',
+ revision: 26,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ lastReadMessage: {
+ id: 'CMG-4348-8387-0436',
+ revision: 1,
+ content: 'update test',
+ visibility: 'Public',
+ isDeleted: false,
+ },
+ unreadMessageCount: 0,
+ },
+ content: 'in theory works for me \\:P',
+ visibility: 'Public',
+ isDeleted: false,
+ links: [],
+ identity: {
+ id: 'USR-2022-1452',
+ name: 'Michal Walczak',
+ icon: '/v1/accounts/users/USR-2022-1452/icon',
+ revision: 26,
+ },
+ audit: {
+ deleted: {},
+ madePublic: {},
+ madePrivate: {},
+ created: {
+ at: '2026-03-05T15:03:42.982Z',
+ by: {
+ id: 'USR-2022-1452',
+ name: 'Michal Walczak',
+ icon: '/v1/accounts/users/USR-2022-1452/icon',
+ revision: 26,
+ },
+ },
+ updated: {},
+ },
+ },
+ {
+ id: 'CMG-0116-4988-6292',
+ revision: 1,
+ chat: {
+ id: 'CHT-4253-7222-5702',
+ revision: 1,
+ type: 'Direct',
+ },
+ sender: {
+ id: 'CHP-4768-7226-5802',
+ revision: 10,
+ chat: {
+ id: 'CHT-4253-7222-5702',
+ revision: 1,
+ type: 'Direct',
+ },
+ contact: {
+ id: 'CTT-4634-2964',
+ name: 'MIchal Walczak',
+ revision: 1,
+ email: 'michal.walczak@softwareone.com',
+ identity: {
+ id: 'USR-2022-1452',
+ name: 'Michal Walczak',
+ icon: '/v1/accounts/users/USR-2022-1452/icon',
+ revision: 26,
+ },
+ },
+ identity: {
+ id: 'USR-2022-1452',
+ name: 'Michal Walczak',
+ icon: '/v1/accounts/users/USR-2022-1452/icon',
+ revision: 26,
+ },
+ account: {
+ id: 'ACC-1032-0145',
+ name: 'SoftwareOne',
+ icon: '/v1/accounts/accounts/ACC-1032-0145/icon',
+ revision: 4,
+ type: 'Operations',
+ status: 'Enabled',
+ },
+ muted: false,
+ status: 'Active',
+ lastReadMessage: {
+ id: 'CMG-4348-8387-0436',
+ revision: 1,
+ content: 'update test',
+ visibility: 'Public',
+ isDeleted: false,
+ },
+ unreadMessageCount: 0,
+ },
+ content:
+ 'When an unknown printer took a galley of type and scrambled it to make a type specimen book.',
+ visibility: 'Public',
+ isDeleted: false,
+ links: [],
+ identity: {
+ id: 'USR-2022-1452',
+ name: 'Michal Walczak',
+ icon: '/v1/accounts/users/USR-2022-1452/icon',
+ revision: 26,
+ },
+ audit: {
+ deleted: {},
+ madePublic: {},
+ madePrivate: {},
+ created: {
+ at: '2026-03-12T15:03:35.336Z',
+ by: {
+ id: 'USR-2022-1452',
+ name: 'Michal Walczak',
+ icon: '/v1/accounts/users/USR-2022-1452/icon',
+ revision: 26,
+ },
+ },
+ updated: {},
+ },
+ },
+];
diff --git a/app/src/styles/components/button.ts b/app/src/styles/components/button.ts
index cc505dbd..1b585609 100644
--- a/app/src/styles/components/button.ts
+++ b/app/src/styles/components/button.ts
@@ -1,13 +1,18 @@
-import { Color, BorderRadius, Spacing, Shadow, Typography } from '../tokens';
+import type { ViewStyle } from 'react-native';
+
+import { Color, BorderRadius, Spacing, Typography } from '../tokens';
+
+const buttonCommon: ViewStyle = {
+ alignItems: 'center',
+ justifyContent: 'center',
+ borderRadius: BorderRadius.round,
+ paddingVertical: Spacing.spacing2,
+ paddingHorizontal: Spacing.spacing3,
+};
export const buttonStyle = {
- common: {
- alignItems: 'center',
- justifyContent: 'center',
- borderRadius: BorderRadius.round,
- paddingVertical: Spacing.spacing2,
- },
primaryLight: {
+ ...buttonCommon,
backgroundColor: Color.brand.white,
color: Color.brand.primary,
},
@@ -17,30 +22,22 @@ export const buttonStyle = {
fontWeight: Typography.fontWeight.regular,
},
primary: {
+ ...buttonCommon,
backgroundColor: Color.brand.primary,
- borderRadius: BorderRadius.xs,
- paddingVertical: Spacing.spacing2,
- paddingHorizontal: Spacing.spacing3,
- alignItems: 'center' as const,
- justifyContent: 'center' as const,
- ...Shadow.sm,
+ },
+ primaryIconOnly: {
+ paddingVertical: Spacing.spacingSmall6,
+ paddingHorizontal: Spacing.spacingSmall6,
},
secondary: {
+ ...buttonCommon,
backgroundColor: Color.alerts.info1,
borderWidth: 1,
borderColor: Color.alerts.info1,
borderRadius: BorderRadius.md,
- paddingVertical: Spacing.spacing2,
- paddingHorizontal: Spacing.spacing3,
- alignItems: 'center' as const,
- justifyContent: 'center' as const,
},
authPrimary: {
- height: 48,
- borderRadius: BorderRadius.xl,
- justifyContent: 'center' as const,
- alignItems: 'center' as const,
- paddingHorizontal: Spacing.spacing3,
+ ...buttonCommon,
backgroundColor: Color.brand.primary,
marginBottom: Spacing.spacing2,
},
diff --git a/app/src/styles/components/chat.ts b/app/src/styles/components/chat.ts
new file mode 100644
index 00000000..fbb2c481
--- /dev/null
+++ b/app/src/styles/components/chat.ts
@@ -0,0 +1,101 @@
+import type { ViewStyle, TextStyle } from 'react-native';
+
+import { BorderRadius, Color, Spacing, Typography } from '../tokens';
+
+const AVATAR_OFFSET_HORIZONTAL = 48;
+const AVATAR_OFFSET_VERTICAL = 22;
+
+const containerCommon: ViewStyle = {
+ flexDirection: 'row',
+ gap: Spacing.spacing2,
+ alignItems: 'flex-start',
+};
+
+const chatTextCommon: TextStyle = {
+ fontSize: Typography.fontSize.font2,
+ fontWeight: Typography.fontWeight.regular,
+ lineHeight: Typography.lineHeight.height3,
+};
+
+const textContainerCommon: ViewStyle = {
+ padding: Spacing.spacing2,
+ borderRadius: BorderRadius.sm,
+ marginBottom: Spacing.spacing2,
+};
+
+const infoCommon: ViewStyle = {
+ flexDirection: 'row',
+ gap: Spacing.spacing1,
+ marginBottom: Spacing.spacingSmall4,
+};
+
+export const chatStyle = {
+ detailsHeaderContainer: {
+ paddingBottom: Spacing.spacing0,
+ },
+ detailsHeaderTopRow: {
+ paddingBottom: Spacing.spacing1,
+ },
+ textInputWrapper: {
+ flex: 1,
+ },
+ iconContainer: {
+ paddingBottom: Spacing.spacingSmall6,
+ },
+ inputContainer: {
+ flexDirection: 'row',
+ alignItems: 'flex-end',
+ gap: Spacing.spacing2,
+ padding: Spacing.spacing2,
+ borderTopWidth: 1,
+ borderColor: Color.gray.gray2,
+ backgroundColor: Color.brand.white,
+ },
+} as const;
+
+export const chatMessageStyle = {
+ avatarWrapper: {
+ paddingTop: AVATAR_OFFSET_VERTICAL,
+ },
+ messageWrapper: {
+ flexGrow: 1,
+ flexShrink: 1,
+ },
+ infoText: {
+ color: Color.gray.gray4,
+ },
+ own: {
+ container: {
+ ...containerCommon,
+ },
+ textContainer: {
+ ...textContainerCommon,
+ backgroundColor: Color.brand.primary,
+ marginLeft: AVATAR_OFFSET_HORIZONTAL,
+ },
+ text: {
+ ...chatTextCommon,
+ color: Color.brand.white,
+ },
+ info: {
+ ...infoCommon,
+ justifyContent: 'flex-end',
+ },
+ },
+ other: {
+ container: {
+ ...containerCommon,
+ },
+ textContainer: {
+ ...textContainerCommon,
+ backgroundColor: Color.gray.gray2,
+ },
+ text: {
+ ...chatTextCommon,
+ color: Color.brand.type,
+ },
+ info: {
+ ...infoCommon,
+ },
+ },
+} as const;
diff --git a/app/src/styles/components/common.ts b/app/src/styles/components/common.ts
index 80a669a5..b2162d3c 100644
--- a/app/src/styles/components/common.ts
+++ b/app/src/styles/components/common.ts
@@ -29,6 +29,9 @@ export const screenStyle = {
contentFillContainer: {
flexGrow: 1,
},
+ containerFlex: {
+ flex: 1,
+ },
sectionHeader: {
fontSize: Typography.fontSize.font2,
textTransform: 'uppercase',
diff --git a/app/src/styles/components/index.ts b/app/src/styles/components/index.ts
index 799301bc..c35d1d3e 100644
--- a/app/src/styles/components/index.ts
+++ b/app/src/styles/components/index.ts
@@ -18,3 +18,4 @@ export { linkStyle } from './link';
export { textStyle } from './text';
export { chipStyle } from './chip';
export { badgeStyle } from './badge';
+export { chatStyle, chatMessageStyle } from './chat';
diff --git a/app/src/styles/components/input.ts b/app/src/styles/components/input.ts
index a6b297f6..4cc8bdb1 100644
--- a/app/src/styles/components/input.ts
+++ b/app/src/styles/components/input.ts
@@ -4,10 +4,10 @@ export const inputStyle = {
container: {
borderWidth: 1,
borderColor: Color.gray.gray4,
- borderRadius: BorderRadius.sm,
+ borderRadius: BorderRadius.xl,
backgroundColor: Color.brand.white,
paddingHorizontal: Spacing.spacing2,
- paddingVertical: Spacing.spacing2,
+ paddingVertical: Spacing.spacing1,
},
transparent: {
borderWidth: 1,
@@ -53,4 +53,10 @@ export const inputStyle = {
color: Color.brand.danger,
marginTop: Spacing.spacing1,
},
+ inputFullWidth: {
+ flexGrow: 1,
+ },
+ inputChat: {
+ maxHeight: 100,
+ },
} as const;
diff --git a/app/src/styles/components/listItem.ts b/app/src/styles/components/listItem.ts
index 949e82e8..93154fac 100644
--- a/app/src/styles/components/listItem.ts
+++ b/app/src/styles/components/listItem.ts
@@ -1,8 +1,32 @@
+import type { ViewStyle } from 'react-native';
+
import { Color, Spacing, Typography, BorderRadius } from '../tokens';
import { badgeStyle } from './badge';
import { separatorStyle } from './separator';
+const avatarWrapperCommon: ViewStyle = {
+ borderRadius: 11,
+ overflow: 'hidden',
+ marginRight: Spacing.spacingSmall12,
+};
+
+const detailsHeaderContainerCommon: ViewStyle = {
+ backgroundColor: Color.brand.white,
+ paddingHorizontal: Spacing.spacing2,
+ paddingBottom: Spacing.spacing2,
+ flexDirection: 'column',
+ borderBottomWidth: 1,
+ borderBottomColor: Color.gray.gray2,
+};
+
+const detailsHeaderTopRowCommon: ViewStyle = {
+ flexDirection: 'row',
+ alignItems: 'center',
+ paddingBottom: Spacing.spacing2,
+ paddingTop: Spacing.spacingSmall4,
+};
+
export const listItemStyle = {
container: {
flexDirection: 'row',
@@ -42,9 +66,12 @@ export const listItemStyle = {
},
textAndImage: {
avatarWrapper: {
- borderRadius: 11,
- overflow: 'hidden',
- marginRight: Spacing.spacingSmall12,
+ ...avatarWrapperCommon,
+ },
+ avatarWrapperChat: {
+ borderRadius: BorderRadius.round,
+ borderColor: Color.gray.gray2,
+ borderWidth: 1,
},
contentWrapper: {
paddingVertical: Spacing.spacing1,
@@ -107,18 +134,33 @@ export const listItemStyle = {
},
},
detailsHeaderContainer: {
- backgroundColor: Color.brand.white,
- paddingHorizontal: Spacing.spacing2,
- paddingBottom: Spacing.spacing2,
- flexDirection: 'column',
- borderBottomWidth: 1,
- borderBottomColor: separatorStyle.nonOpaque.borderColor,
+ default: {
+ ...detailsHeaderContainerCommon,
+ },
+ chat: {
+ ...detailsHeaderContainerCommon,
+ paddingBottom: 0,
+ },
},
detailsHeaderTopRow: {
- flexDirection: 'row',
- alignItems: 'center',
- paddingBottom: 16,
- paddingTop: 4,
+ default: {
+ ...detailsHeaderTopRowCommon,
+ },
+ chat: {
+ ...detailsHeaderTopRowCommon,
+ paddingBottom: Spacing.spacing1,
+ },
+ },
+ detailsHeaderAvatarWrapper: {
+ default: {
+ ...avatarWrapperCommon,
+ },
+ chat: {
+ ...avatarWrapperCommon,
+ borderRadius: BorderRadius.round,
+ borderColor: Color.gray.gray2,
+ borderWidth: 1,
+ },
},
detailsHeaderTitle: {
fontSize: Typography.fontSize.font5,
@@ -162,14 +204,14 @@ export const listItemChatStyle = {
topRow: {
flexDirection: 'row',
alignItems: 'center',
- marginBottom: 4,
+ marginBottom: Spacing.spacingSmall4,
},
titleWrapper: {
flexShrink: 1,
minWidth: 0,
},
separator: {
- paddingHorizontal: 4,
+ paddingHorizontal: Spacing.spacingSmall4,
fontSize: Typography.fontSize.font2,
color: Color.gray.gray4,
},
diff --git a/app/src/types/chat.ts b/app/src/types/chat.ts
index 261177e6..a867cbb9 100644
--- a/app/src/types/chat.ts
+++ b/app/src/types/chat.ts
@@ -2,6 +2,25 @@ import type { ListItemCommonProps } from '@/types/lists';
export type ChatType = 'Direct' | 'Group' | 'Channel' | 'Case';
+export type MessageType = 'own' | 'other';
+
+export type Audit = {
+ created?: {
+ at: string;
+ by: unknown;
+ };
+ updated?: unknown;
+ deleted?: unknown;
+ madePublic?: unknown;
+ madePrivate?: unknown;
+};
+
+export type Chat = {
+ id: string;
+ type: ChatType;
+ revision: number;
+};
+
export type Identity = {
id: string;
name: string;
@@ -23,6 +42,7 @@ export type Account = {
icon?: string;
type: string;
status: string;
+ revision?: number;
};
export type ChatParticipant = {
@@ -31,16 +51,23 @@ export type ChatParticipant = {
contact?: Contact;
account?: Account;
unreadMessageCount: number;
+ revision?: number;
+};
+
+export type Sender = ChatParticipant & {
+ chat: Chat;
+ muted: boolean;
+ status: string;
+ lastReadMessage: LastMessage;
};
export type LastMessage = {
id: string;
content: string;
- audit?: {
- created?: {
- at: string;
- };
- };
+ audit?: Audit;
+ revision?: number;
+ visibility?: string;
+ isDeleted: boolean;
};
export type ChatItem = {
@@ -66,3 +93,16 @@ export type ListItemChatProps = ListItemCommonProps & {
avatars: AvatarItem[];
isVerified: boolean;
};
+
+export type Message = {
+ id: string;
+ revision: number;
+ chat: Chat;
+ sender: Sender;
+ identity: Identity;
+ content: string;
+ visibility: 'Public' | 'Private';
+ isDeleted: boolean;
+ links: unknown[];
+ audit: Audit;
+};
diff --git a/app/src/types/lists.ts b/app/src/types/lists.ts
index 58ab6c3f..1656f599 100644
--- a/app/src/types/lists.ts
+++ b/app/src/types/lists.ts
@@ -15,6 +15,7 @@ export type ListItemWithStatusProps = ListItemCommonProps & {
title: string;
subtitle?: string;
statusText: string;
+ variant?: 'default' | 'chat';
};
export type ListItemConfig = {
diff --git a/app/src/utils/formatting.ts b/app/src/utils/formatting.ts
index a4c5cd4c..110ba657 100644
--- a/app/src/utils/formatting.ts
+++ b/app/src/utils/formatting.ts
@@ -79,15 +79,7 @@ export const getDatePartsForLocale = (
timeZone: 'UTC',
}).formatToParts(date);
- const timeParts = new Intl.DateTimeFormat(locale, {
- hour: '2-digit',
- minute: '2-digit',
- timeZone: 'UTC',
- }).formatToParts(date);
-
return {
- hour: timeParts.find((p) => p.type === 'hour')?.value,
- minute: timeParts.find((p) => p.type === 'minute')?.value,
weekday: dateParts.find((p) => p.type === 'weekday')?.value,
day: dateParts.find((p) => p.type === 'day')?.value,
month: dateParts.find((p) => p.type === 'month')?.value,
@@ -187,25 +179,26 @@ export const formatDateForChat = (isoDate: string | undefined, locale: string):
const diffMs = now.getTime() - date.getTime();
const parts = getDatePartsForLocale(isoDate, locale);
+ const time = getTime(isoDate);
if (!parts) {
return EMPTY_STRING;
}
- const { hour, minute, weekday, day, month, year } = parts;
+ const { weekday, day, month, year } = parts;
- if (!hour || !minute || !weekday || !day || !month || !year) {
+ if (!weekday || !day || !month || !year) {
return EMPTY_STRING;
}
// within last 24 hours - HH:MM
if (diffMs < MS_PER_DAY) {
- return `${hour}:${minute}`;
+ return time;
}
// within last 7 days - Weekday
if (diffMs < DAYS_PER_WEEK * MS_PER_DAY) {
- return weekday || EMPTY_STRING;
+ return weekday;
}
// within current year - DD Mon