Mobile Chat Adaptation: New Components and Optimizations
The team has implemented full mobile responsiveness for WebView-based applications with streamlined functionality to reduce load. Added the RNNoiser library for audio processing, a scheduled messages feature, revamped the input with expanded formatting, reduced request latency, and optimized data storage. All changes are aimed at mid/senior developers working with React Native and WebView.
Adaptive UI for Touch Interfaces
Developed MobileBottomNav — a minimalist bottom navigation bar with five tabs: servers, chats, kanban, search, and profile. The component is stateless, passing only the active view ID via onViewChange without internal logic or API calls.
import { Icon } from '@shared/ui/Icon';
import { UserAvatar } from '@shared/ui/UserAvatar';
export function MobileBottomNav({
currentView,
onViewChange,
user
}) {
const tabs = [
{ id: 'general-chats', icon: 'groupChat', label: 'Servers' },
{ id: 'direct-chats', icon: 'chat', label: 'Chats' },
{ id: 'chat-board', icon: 'board', label: 'Kanban' },
{ id: 'mobile-search', icon: 'search', label: 'Search' },
{ id: 'profile', label: 'Profile', isProfile: true },
];
return (
<nav className="mobile-bottom-nav">
{tabs.map(tab => (
<button
key={tab.id}
className={`mobile-bottom-nav-tab ${currentView === tab.id ? 'active' : ''}`}
onClick={() => onViewChange(tab.id)}
>
<span className="mobile-bottom-nav-icon">
{tab.isProfile ? (
<UserAvatar
avatar={user?.avatar}
userId={user?.user_id}
username={user?.username}
status={user?.status}
size={28}
showStatus={false}
className="mobile-bottom-nav-avatar"
/>
) : (
<Icon name={tab.icon} size={22} />
)}
</span>
<span className="mobile-bottom-nav-label">{tab.label}</span>
</button>
))}
</nav>
);
}
The profile tab uses UserAvatar instead of an icon for visual recognition. The parent component handles view switching based on the received ID.
Optimized Server List
Instead of the desktop LeftMenu, MobileServersList was created for touch interactions. The left panel shows server icons in a Discord-like style, the right panel shows topics of the selected server. The component reuses the useLeftMenu hook for business logic: loading lists, WebSocket events, creating servers. This minimizes code duplication and eliminates rendering lags from the desktop layout.
Tapping a server updates the topics on the right without a full reload. Tapping a topic opens the chat.
Revamped Input with Expanded Formatting
The input is adapted to the Mattermost format, preventing editor element wrapping. Functionality includes:
- Bold and italic: standard Markdown formatting.
- Code block: syntax highlighting for inserting snippets.
- PlantUML diagrams: generating UML from text markup directly in the message.
- Quote: block highlighting with >.
- Link: embedding hyperlinks.
- List: bulleted or numbered.
- Poll: interactive voting.
This allows senior developers to exchange technical content without external tools.
Context Menus and Gestures
The bottom menu is activated by a long tap — reusing an existing component with mobile styles under isMobile. Message reactions open in an adaptive overlay. The right menu is optimized with CSS and conditional logic for mobile devices.
A separate "Scheduled" section aggregates all planned messages for quick scheduler overview.
Mobile User Profile
Created a dedicated MobileProfilePage component with a user card, status, and settings sections.
return (
<div className="mobile-profile-page">
<div className="mobile-profile-page-header">
<div className="mobile-profile-user-card">
<div className="mobile-profile-avatar">
{avatarUrl ? (
<img src={avatarUrl} alt={user.username} className="mobile-profile-avatar-img" />
) : (
<div className="mobile-profile-avatar-placeholder">{initials}</div>
)}
<span className={`status-icon ${user.status || 'offline'} mobile-profile-status"></span>
</div>
<div className="mobile-profile-info">
<div className="mobile-profile-username">{user.username}</div>
<div className="mobile-profile-handle">{user.handle || `@${user.username}`}</div>
</div>
</div>
</div>
<div className="mobile-profile-page-content">
<div className="mobile-profile-section">
<div className="mobile-profile-item" onClick={onOpenProfile}>
<span className="mobile-profile-item-icon"><Icon name="user" size={20} /></span>
<span className="mobile-profile-item-text">Edit Profile</span>
<span className="mobile-profile-item-arrow"><Icon name="chevronRight" size={16} /></span>
</div>
{/* Other items similarly */}
</div>
{/* Status and logout sections */}
</div>
</div>
);
Each item triggers a callback; the component does not manage modals or navigation.
Additional Improvements
- RNNoiser: integrated to reduce noise in voice messages and calls.
- Latency: optimized requests through caching and batching.
- Data storage: completely rebuilt considering mobile memory constraints.
These changes ensure performance on low-end devices without compromising functionality.
Key Takeaways
- Full WebView responsiveness with separate components for touch interfaces.
- Reusing business logic via hooks without duplication.
- Expanded input with PlantUML and polls for technical chats.
- Scheduled messages in a dedicated section for planning convenience.
- Stateless approach in UI components for predictable rendering.
— Editorial Team
No comments yet.