diff --git a/.github/workflows/ISSUE_TEMPLATE/bug_report.md b/.github/workflows/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..ef0e9b6
--- /dev/null
+++ b/.github/workflows/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,36 @@
+---
+name: Bug report
+about: Create a report to help us improve Open MobileUI
+title: '[BUG]'
+labels: bug, for review
+assignees: ipakhomov
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+
+1. Go to '...'
+2. Press on '....'
+3. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Versions**
+
+- Open MobileUI app version: [e.g. v1.5.0]
+- Open WebUI API version: [e.g. v0.7.2]
+
+**Platform**
+
+- Device: [e.g. iPhone 15]
+- OS: [e.g. iOS 26.1]
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/.github/workflows/ISSUE_TEMPLATE/feature_request.md b/.github/workflows/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..34b4650
--- /dev/null
+++ b/.github/workflows/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,25 @@
+---
+name: Feature request
+about: Suggest an idea to enhance Open MobileUI
+title: '[FEATURE]'
+labels: enhancement, for review
+assignees: ipakhomov
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Does this feature available in Open WebUI?**
+Describe whether there is an existing feature in Open WebUI for web.
+
+**Why is this feature important to you?**
+Describe, how much would it enhance your experience.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..e86352e
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,95 @@
+# Contributing to Open MobileUI
+
+Thanks for your interest in improving Open MobileUI! Bug fixes, new features, documentation, UI/UX polish, performance work, and translations are all welcome.
+
+## Ways to contribute
+
+- 🐛 **Bug fixes** — help us squash bugs and improve stability
+- ✨ **Features** — propose and build new functionality
+- 📝 **Documentation** — improve docs, add examples, fix typos
+- 🎨 **UI/UX** — refine the mobile experience
+- ⚡ **Performance** — optimize rendering and app responsiveness
+- 🌍 **Internationalization** — add translations for new languages
+
+## Reporting issues
+
+Before opening an issue, please [search existing issues](https://github.com/RonasIT/open-webui-react-native/issues) to avoid duplicates.
+
+When [filing a new issue](https://github.com/RonasIT/open-webui-react-native/issues/new/choose), pick the template that fits:
+
+- 🐛 **Bug report** — for something that's broken. Fill in what happened vs. what you expected, precise steps to reproduce, the app + Open WebUI versions, your device + OS, and screenshots where relevant.
+- ✨ **Feature request** — for new functionality. Describe the use case and the problem it solves, not just the proposed solution.
+
+## Development setup
+
+### Prerequisites
+
+- **Node.js** 18+ and npm
+- **iOS:** Xcode 14+ (macOS only)
+- **Android:** Android Studio with the Android SDK
+
+### Clone and install
+
+```bash
+git clone https://github.com/RonasIT/open-webui-react-native.git
+cd open-webui-react-native
+npm install
+```
+
+### Run the app
+
+```bash
+# Start the Metro bundler (development env)
+npx nx start mobile
+
+# Or run directly on a device/emulator (from apps/mobile)
+npm run android
+npm run ios
+```
+
+Running on a device/emulator requires a **development build**. Follow the
+[Expo development builds guide](https://docs.expo.dev/develop/development-builds/create-a-build/)
+to create one (a one-time setup), then start the bundler as above.
+
+### Configure your own Expo project (for builds)
+
+To create your own builds you'll need an Expo project of your own:
+
+1. Create an account at [expo.dev](https://expo.dev/) and a new project.
+2. Note your project `slug`, `owner`, and `project ID`.
+3. Provide your project details via environment variables / app config used by
+ [`apps/mobile/app.config.ts`](apps/mobile/app.config.ts) (e.g. `EXPO_PUBLIC_APP_NAME`,
+ `EXPO_PUBLIC_APP_SLUG`, `EXPO_PUBLIC_APP_OWNER`, `EXPO_PUBLIC_PROJECT_ID`).
+4. For production builds, configure [`eas.json`](eas.json) following the
+ [EAS configuration guide](https://docs.expo.dev/eas/json/).
+
+### Common commands
+
+```bash
+npm run lint # tsc + eslint
+npm run format # prettier + eslint --fix
+npx nx test mobile # run the mobile test suite
+```
+
+See the root [CLAUDE.md](CLAUDE.md) and `README.md` for more on the monorepo architecture and library structure.
+
+## Submitting a pull request
+
+1. **Fork** the repository and create a feature branch off `main`.
+2. Make your changes, keeping commits focused and following the existing code style.
+3. **Run `npm run lint`** and the relevant tests — make sure everything passes.
+4. **Open a pull request** against `main` with a clear description of _what_ changed and _why_. Link any related issue.
+5. Be ready to iterate on review feedback.
+
+For larger changes, please open an issue to discuss the approach first — it saves everyone time.
+
+## Helpful resources
+
+- 📖 [Expo development builds](https://docs.expo.dev/develop/development-builds/create-a-build/)
+- 📦 [EAS Build documentation](https://docs.expo.dev/build/setup/)
+- ⚙️ [Expo configuration reference](https://docs.expo.dev/workflow/configuration/)
+- 🏗️ [Nx documentation](https://nx.dev/getting-started/intro)
+
+---
+
+By contributing, you agree that your contributions will be licensed under the project's [GPL v3 license](LICENSE).
diff --git a/README.md b/README.md
index 39581fb..1612034 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,9 @@
-# Open MobileUI
-
+

+
+# Open MobileUI
+



@@ -9,7 +11,17 @@
**Professional mobile client for Open WebUI** – Access your self-hosted AI assistant anywhere, anytime
-[Features](#features) • [Installation](#installation) • [Development](#development) • [Support](#support) • [Privacy Policy](PRIVACY_POLICY.md)
+[Features](#-features) • [Installation](#-installation) • [Development](#️-development) • [Support](#-support) • [Privacy Policy](PRIVACY_POLICY.md)
+
+
+
+
+
+
+
+
+
+
@@ -48,7 +60,7 @@ While Open WebUI works in mobile browsers, Open MobileUI provides:
- ✅ **Multi-Model Support** – Switch between different AI models seamlessly
- ✅ **Chat Management** – Organize conversations with folders, search, and archive functionality
- ✅ **Authentication** – Email/password and Google Sign-In support (requires additional setup)
-- ✅ **Secure Connections** – Supports encrypted HTTPS/WSS connections to your self-hosted Open WebUI instance (use HTTPS URLs for encrypted communication)
+- ✅ **Secure Connections** – Encrypted HTTPS/WSS connections to your self-hosted Open WebUI instance
### Mobile-Optimized Experience
@@ -59,72 +71,26 @@ While Open WebUI works in mobile browsers, Open MobileUI provides:
- 🌙 **Dark Mode** – System-aware theme support for comfortable viewing in any lighting
- ⌨️ **Keyboard Optimization** – Intelligent keyboard handling and input management
-### Enterprise Features
+### Coming Soon
-- 🏢 **Self-Hosted Ready** – Connect to your private Open WebUI deployment
-- 🔐 **Security First** – Secure credential storage, encrypted connections, and privacy-focused architecture
-- 📊 **Offline Mode** – Graceful handling of network interruptions
-- 🔔 **Real-time Updates** – Live notifications and instant message delivery
-- 🌍 **Internationalization** – Multi-language support (coming soon)
+- 🌍 **Internationalization** – Multi-language support
+- 🎙️ **Voice Mode** – Hands-free voice input
---
## 🎯 Use Cases
-### For Individuals
-
-- **On-the-Go AI Assistant** – Access your personal AI assistant from anywhere
-- **Mobile Productivity** – Get instant answers and assistance without opening a laptop
-- **Privacy-Conscious Users** – Keep your conversations private with self-hosted infrastructure
-
-### For Businesses
-
-- **Team Collaboration** – Enable your team to access company AI assistants from mobile devices
-- **Field Operations** – Support remote workers and field teams with mobile AI access
-- **Cost Efficiency** – Leverage self-hosted infrastructure without per-user mobile app licensing fees
-- **Enterprise Security** – Maintain full control over data and conversations with on-premise deployment
-
-### For Developers
-
-- **Open Source Alternative** – Professional-grade mobile client for the Open WebUI ecosystem
-- **Reference Implementation** – Well-architected React Native codebase using modern best practices
-- **Extensible Platform** – Built with modular architecture for easy customization and extension
+- **Individuals** – An on-the-go AI assistant for instant answers without reaching for a laptop
+- **Businesses** – Mobile access to company AI assistants for teams and field workers, with no per-user app licensing fees
+- **Developers** – A well-architected, extensible React Native reference client for the Open WebUI ecosystem
## 📥 Installation
-### Quick Start
-
-Get started in minutes with pre-built releases or build from source.
-
-### Option 1: Download Pre-built App (Recommended)
-
-#### Android
-
-1. Download the latest `.apk` file from [GitHub Releases](https://github.com/RonasIT/open-webui-react-native/releases)
-2. Enable "Install from Unknown Sources" in your Android device settings
-3. Install the APK file
-4. Launch the app and enter your Open WebUI instance URL
-
-#### iOS
-
-iOS builds are available through TestFlight or App Store (coming soon). Check [Releases](https://github.com/RonasIT/open-webui-react-native/releases) for TestFlight links.
-
-### Option 2: Build from Source
-
-See the [Development](#development) section below for detailed build instructions.
-
-### System Requirements
-
-- **Open WebUI**: active instance with accessible URL
-- **Android**: Android 8.0 (API level 26) or higher
-- **iOS**: iOS 13 or higher
-
-### First-Time Setup
-
-1. **Launch the App** – Open the installed application
-2. **Enter Server URL** – Provide your Open WebUI instance URL (e.g., `https://your-instance.com`)
-3. **Authenticate** – Sign in with your Open WebUI credentials (email/password)
-4. **Start Chatting** – You're ready to use your AI assistant on mobile!
+1. **Install the App** – Download Open MobileUI from the [App Store](https://apps.apple.com/us/app/open-mobileui/id6754266176) or [Google Play](https://play.google.com/store/apps/details?id=com.open.web.ui)
+2. **Launch the App** – Open the installed application
+3. **Enter Server URL** – Provide your Open WebUI instance URL (e.g., `https://your-instance.com`)
+4. **Authenticate** – Sign in with your Open WebUI credentials (email/password)
+5. **Start Chatting** – You're ready to use your AI assistant on mobile!
## 🛠️ Development
@@ -147,105 +113,13 @@ The codebase follows a modular, scalable architecture:
### Building from Source
-#### Prerequisites
-
-- **Node.js** 18+ and npm
-- **Expo CLI** – `npm install -g expo-cli`
-- **EAS CLI** (for builds) – `npm install -g eas-cli`
-- **iOS Development**: Xcode 14+ (macOS only)
-- **Android Development**: Android Studio with Android SDK
-
-#### Step-by-Step Setup
-
-1. **Clone the Repository**
-
-```bash
-git clone https://github.com/RonasIT/open-webui-react-native.git
-cd open-webui-react-native
-```
-
-2. **Install Dependencies**
-
-```bash
-npm install
-```
-
-3. **Configure Expo Project**
-
-- Create an account at [expo.dev](https://expo.dev/) if you don't have one
-- Create a new project or use an existing one
-- Note your project details: `slug`, `owner`, `project ID`
-
-4. **Configure App Settings**
-
-Edit `app.config.js` (or `app.config.ts`) with your project details:
-
-```javascript
-{
- name: "Your App Name",
- slug: "your-app-slug",
- owner: "your-expo-username",
- version: "1.0.0"
- // ... additional configuration
-}
-```
-
-5. **Set Up EAS Build** (Optional, for production builds)
-
-- Create `eas.json` following the [EAS Configuration Guide](https://docs.expo.dev/eas/json/)
-- Configure build profiles, app IDs, and credentials
-
-6. **Start Development**
-
-For development builds:
-
-```bash
-# Create a development build first (one-time setup)
-# Follow: https://docs.expo.dev/develop/development-builds/create-a-build/
-
-# Then start the Metro bundler
-npm start
-```
-
-For production builds:
-
-```bash
-npm run build:prod
-```
-
-### Development Resources
-
-- 📖 [Expo Development Builds Guide](https://docs.expo.dev/develop/development-builds/create-a-build/)
-- 📦 [EAS Build Documentation](https://docs.expo.dev/build/setup/)
-- ⚙️ [Expo Configuration Reference](https://docs.expo.dev/workflow/configuration/)
-- 🏗️ [Nx Documentation](https://nx.dev/getting-started/intro)
+For detailed setup instructions — prerequisites, cloning, configuring your own Expo project, and running the app — see the [Contributing guide](CONTRIBUTING.md#development-setup).
## 🤝 Contributing
We welcome and appreciate contributions from the community! Whether you're fixing bugs, adding features, or improving documentation, your help makes this project better.
-### How to Contribute
-
-1. **Fork the Repository** – Create your own fork of the project
-2. **Create a Branch** – Make your changes in a feature branch
-3. **Follow Guidelines** – Adhere to our code style and commit conventions
-4. **Test Your Changes** – Ensure your changes work correctly
-5. **Submit a Pull Request** – Open a PR with a clear description of your changes
-
-### Contribution Areas
-
-- 🐛 **Bug Fixes** – Help us squash bugs and improve stability
-- ✨ **New Features** – Propose and implement new functionality
-- 📝 **Documentation** – Improve docs, add examples, or fix typos
-- 🎨 **UI/UX Improvements** – Enhance the user experience
-- ⚡ **Performance** – Optimize code and improve app performance
-- 🌍 **Internationalization** – Add translations for new languages
-
-### Getting Help
-
-- 📋 **Report Issues** – Use [GitHub Issues](https://github.com/RonasIT/open-webui-react-native/issues) for bug reports
-- 💬 **Discussions** – Join [Open WebUI Discussions](https://github.com/open-webui/open-webui/discussions) for questions
-- 📧 **Contact** – Reach out to [Ronas IT](https://ronasit.com) for enterprise support
+See [CONTRIBUTING.md](CONTRIBUTING.md) for how to report issues, set up your development environment, and submit a pull request.
---
@@ -275,17 +149,11 @@ For businesses requiring professional support, custom development, or enterprise
### Frequently Asked Questions
**Q: Is this app free to use?**
-A: Yes! This is an open-source project released under the GNU General Public License v3 (GPL v3). You are free to use, modify, and distribute it under the terms of the GPL v3.
+A: Yes — it's open source under GPL v3. Commercial use is allowed; see [License](#-license) for the terms.
**Q: Do I need to host my own Open WebUI instance?**
A: Yes, this app connects to your self-hosted Open WebUI deployment. See [Open WebUI Installation](https://docs.openwebui.com/) for setup instructions.
-**Q: Is my data secure?**
-A: Absolutely. All connections are encrypted, and your data stays on your self-hosted instance. The app never stores or transmits your conversations to third parties. For detailed information about data handling, see our [Privacy Policy](PRIVACY_POLICY.md).
-
-**Q: Can I use this for commercial purposes?**
-A: Yes, GPL v3 allows commercial use. However, if you distribute the software (or modified versions), you must also provide the source code and license your modifications under GPL v3. See the [LICENSE](LICENSE.txt) file for complete terms.
-
**Q: How do I report a security vulnerability?**
A: Please email security concerns directly to our team through [Ronas IT](https://ronasit.com) rather than opening a public issue.
diff --git a/apps/mobile/app/(main)/chat/[id].tsx b/apps/mobile/app/(main)/chat/[id].tsx
index 57ea1f5..b42b239 100644
--- a/apps/mobile/app/(main)/chat/[id].tsx
+++ b/apps/mobile/app/(main)/chat/[id].tsx
@@ -14,7 +14,6 @@ import {
AppText,
Icon,
FullScreenSearchModal,
- AppKeyboardControllerView,
IconButton,
} from '@open-webui-react-native/mobile/shared/ui/ui-kit';
import {
@@ -65,50 +64,48 @@ export default function ChatScreen(): ReactElement {
);
return (
-
-
- )
- }
- onGoBack={handleGoBackPress}
- accessoryRight={
- {
- if (!chat) return;
- chatActionsSheetRef.current?.present(chat);
- }}
+
- }
- />
- }
- scrollDisabled>
-
-
-
-
-
+ )
+ }
+ onGoBack={handleGoBackPress}
+ accessoryRight={
+ {
+ if (!chat) return;
+ chatActionsSheetRef.current?.present(chat);
+ }}
+ />
+ }
+ />
+ }
+ scrollDisabled>
+
+
+
+
);
}
diff --git a/apps/mobile/package.json b/apps/mobile/package.json
index a994a1a..dda6470 100644
--- a/apps/mobile/package.json
+++ b/apps/mobile/package.json
@@ -71,7 +71,7 @@
"react-native-compressor": "^1.12.0",
"react-native-extended-stylesheet": "^0.12.0",
"react-native-gesture-handler": "~2.28.0",
- "react-native-keyboard-controller": "1.18.5",
+ "react-native-keyboard-controller": "1.21.8",
"react-native-mmkv": "^3.2.0",
"react-native-modal": "^14.0.0-rc.1",
"react-native-reanimated": "~4.1.1",
diff --git a/docs/images/app-store.png b/docs/images/app-store.png
new file mode 100644
index 0000000..52d3fb9
Binary files /dev/null and b/docs/images/app-store.png differ
diff --git a/docs/images/google-play.png b/docs/images/google-play.png
new file mode 100644
index 0000000..1890fd1
Binary files /dev/null and b/docs/images/google-play.png differ
diff --git a/docs/images/logo.png b/docs/images/logo.png
new file mode 100644
index 0000000..e62c179
Binary files /dev/null and b/docs/images/logo.png differ
diff --git a/libs/mobile/chat/features/chat/src/lib/component.tsx b/libs/mobile/chat/features/chat/src/lib/component.tsx
index 1813a60..1c885f5 100644
--- a/libs/mobile/chat/features/chat/src/lib/component.tsx
+++ b/libs/mobile/chat/features/chat/src/lib/component.tsx
@@ -1,5 +1,4 @@
import { useSelector } from '@legendapp/state/react';
-import { useKeyboard } from '@react-native-community/hooks';
import { useTranslation } from '@ronas-it/react-native-common-modules/i18n';
import dayjs from 'dayjs';
import { delay } from 'lodash-es';
@@ -14,9 +13,8 @@ import { useSendMessage } from '@open-webui-react-native/mobile/chat/features/us
import { useSuggestChange } from '@open-webui-react-native/mobile/chat/features/use-suggest-change';
import { useAttachedFiles } from '@open-webui-react-native/mobile/shared/features/use-attached-files';
import { cn } from '@open-webui-react-native/mobile/shared/ui/styles';
-import { AppSpinner, View } from '@open-webui-react-native/mobile/shared/ui/ui-kit';
+import { AppKeyboardStickyView, AppSpinner, View } from '@open-webui-react-native/mobile/shared/ui/ui-kit';
import { FormValues } from '@open-webui-react-native/mobile/shared/utils/form';
-import { useBottomInset } from '@open-webui-react-native/mobile/shared/utils/use-bottom-inset';
import { chatApi, ChatGenerationOption, chatQueriesKeys } from '@open-webui-react-native/shared/data-access/api';
import { Role } from '@open-webui-react-native/shared/data-access/common';
import { useSubscribeToQueryCache } from '@open-webui-react-native/shared/data-access/query-client';
@@ -38,8 +36,6 @@ interface ChatProps {
export function Chat({ chatId, selectedModelId, isNewChat, resetToChatsList }: ChatProps): ReactElement {
const translate = useTranslation('CHAT.CHAT');
const translateRegeneratePrompt = useTranslation('CHAT.AI_MESSAGE_ACTIONS.REGENERATE_MESSAGE_ACTION_SHEET');
- const bottomInset = useBottomInset();
- const { keyboardShown } = useKeyboard();
const [isInputFocusing, setIsInputFocusing] = useState(false); //NOTE: Needs to avoid ChatBottomButton jumping when auto-scrolling after focus
@@ -225,47 +221,47 @@ export function Chat({ chatId, selectedModelId, isNewChat, resetToChatsList }: C
/>
)}
-
- {activeInputMode === ActiveInputMode.EDIT && editingMessageId ? (
-
- ) : activeInputMode === ActiveInputMode.SUGGEST && suggestingMessageId ? (
-
- ) : (
-
- )}
-
+
+
+ {activeInputMode === ActiveInputMode.EDIT && editingMessageId ? (
+
+ ) : activeInputMode === ActiveInputMode.SUGGEST && suggestingMessageId ? (
+
+ ) : (
+
+ )}
+
+
);
}
diff --git a/libs/mobile/chat/features/chat/src/lib/components/chat-bottom-button/component.tsx b/libs/mobile/chat/features/chat/src/lib/components/chat-bottom-button/component.tsx
index 2ff66de..b3b71d9 100644
--- a/libs/mobile/chat/features/chat/src/lib/components/chat-bottom-button/component.tsx
+++ b/libs/mobile/chat/features/chat/src/lib/components/chat-bottom-button/component.tsx
@@ -13,7 +13,7 @@ export default function ChatBottomButton({ isVisible, onPress }: ChatBottomButto
}));
return (
-
+
, []);
+
const handleContentSizeChange = (): void => {
//NOTE: Needs to wait until the initial scroll to the bottom or content generation finished and not show the ChatBottomButton before
isScrollToBottomAvailable.current = false;
@@ -89,11 +91,7 @@ export default function ChatMessagesList({
if (!isMessagesListLoaded && listRef.current && messages?.length > 0) {
delay(() => {
- listRef.current?.scrollToIndex({
- index: messages.length - 1,
- animated: false,
- viewPosition: 1,
- });
+ listRef.current?.scrollToEnd({ animated: false });
delay(onLayout, 125);
}, 125);
}
@@ -261,7 +259,7 @@ export default function ChatMessagesList({
ref={listRef}
- contentContainerClassName='pb-16 px-16'
+ contentContainerClassName='pb-[135] px-16'
showsVerticalScrollIndicator={false}
drawDistance={1500} //NOTE: Needs to avoid image jumping (while rerendering) when scrolling
keyExtractor={(item) => item.id}
@@ -272,6 +270,7 @@ export default function ChatMessagesList({
maintainVisibleContentPosition={{
startRenderingFromBottom: true,
}}
+ renderScrollComponent={renderScrollComponent}
onContentSizeChange={handleContentSizeChange}
onScroll={handleScroll}
onTouchStart={handleTouchStart}
diff --git a/libs/mobile/shared/ui/ui-kit/src/index.ts b/libs/mobile/shared/ui/ui-kit/src/index.ts
index 0e4305f..79bf826 100644
--- a/libs/mobile/shared/ui/ui-kit/src/index.ts
+++ b/libs/mobile/shared/ui/ui-kit/src/index.ts
@@ -39,6 +39,8 @@ export * from './header';
export * from './full-screen-modal';
export * from './sheet-header';
export * from './keyboard-aware-scroll-view';
+export * from './keyboard-chat-scroll-view';
+export * from './keyboard-sticky-view';
export * from './pressable-search-input';
export * from './full-screen-search-modal';
export * from './gesture-pressable-icon-button';
diff --git a/libs/mobile/shared/ui/ui-kit/src/keyboard-chat-scroll-view/component.tsx b/libs/mobile/shared/ui/ui-kit/src/keyboard-chat-scroll-view/component.tsx
new file mode 100644
index 0000000..37ae2b7
--- /dev/null
+++ b/libs/mobile/shared/ui/ui-kit/src/keyboard-chat-scroll-view/component.tsx
@@ -0,0 +1,34 @@
+import { cssInterop } from 'nativewind';
+import { ReactElement } from 'react';
+import { KeyboardChatScrollView, KeyboardChatScrollViewProps } from 'react-native-keyboard-controller';
+import { cn } from '@open-webui-react-native/mobile/shared/ui/styles';
+
+const CustomizedKeyboardChatScrollView = cssInterop(KeyboardChatScrollView, {
+ className: 'style',
+ contentContainerClassName: 'contentContainerStyle',
+});
+
+type AppKeyboardChatScrollViewProps = KeyboardChatScrollViewProps & {
+ className?: string;
+ contentContainerClassName?: string;
+};
+
+export function AppKeyboardChatScrollView({
+ className,
+ contentContainerClassName,
+ offset = 20,
+ automaticallyAdjustContentInsets = false,
+ contentInsetAdjustmentBehavior = 'never',
+ ...restProps
+}: AppKeyboardChatScrollViewProps): ReactElement {
+ return (
+
+ );
+}
diff --git a/libs/mobile/shared/ui/ui-kit/src/keyboard-chat-scroll-view/index.ts b/libs/mobile/shared/ui/ui-kit/src/keyboard-chat-scroll-view/index.ts
new file mode 100644
index 0000000..bb82484
--- /dev/null
+++ b/libs/mobile/shared/ui/ui-kit/src/keyboard-chat-scroll-view/index.ts
@@ -0,0 +1 @@
+export * from './component';
diff --git a/libs/mobile/shared/ui/ui-kit/src/keyboard-sticky-view/component.tsx b/libs/mobile/shared/ui/ui-kit/src/keyboard-sticky-view/component.tsx
new file mode 100644
index 0000000..c5a2860
--- /dev/null
+++ b/libs/mobile/shared/ui/ui-kit/src/keyboard-sticky-view/component.tsx
@@ -0,0 +1,30 @@
+import { AppSafeAreaView } from '@ronas-it/react-native-common-modules/safe-area-view';
+import { PropsWithChildren, ReactElement } from 'react';
+import { KeyboardStickyView, KeyboardStickyViewProps } from 'react-native-keyboard-controller';
+import { Edge } from 'react-native-safe-area-context';
+import { cn } from '@open-webui-react-native/mobile/shared/ui/styles';
+
+type AppKeyboardStickyViewProps = PropsWithChildren<
+ KeyboardStickyViewProps & {
+ className?: string;
+ safeAreaEdges?: Array;
+ }
+>;
+
+export function AppKeyboardStickyView({
+ className,
+ offset = { opened: 20, closed: 0 },
+ style,
+ children,
+ safeAreaEdges = ['bottom'],
+ ...restProps
+}: AppKeyboardStickyViewProps): ReactElement {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/libs/mobile/shared/ui/ui-kit/src/keyboard-sticky-view/index.ts b/libs/mobile/shared/ui/ui-kit/src/keyboard-sticky-view/index.ts
new file mode 100644
index 0000000..bb82484
--- /dev/null
+++ b/libs/mobile/shared/ui/ui-kit/src/keyboard-sticky-view/index.ts
@@ -0,0 +1 @@
+export * from './component';
diff --git a/package-lock.json b/package-lock.json
index bfdd980..bacde44 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -80,7 +80,7 @@
"react-native-compressor": "^1.12.0",
"react-native-extended-stylesheet": "^0.12.0",
"react-native-gesture-handler": "~2.28.0",
- "react-native-keyboard-controller": "1.18.5",
+ "react-native-keyboard-controller": "1.21.8",
"react-native-markdown-display": "^7.0.2",
"react-native-mathjax-svg": "^0.9.9",
"react-native-mmkv": "^3.2.0",
@@ -208,7 +208,7 @@
"react-native-compressor": "^1.12.0",
"react-native-extended-stylesheet": "^0.12.0",
"react-native-gesture-handler": "~2.28.0",
- "react-native-keyboard-controller": "1.18.5",
+ "react-native-keyboard-controller": "1.21.8",
"react-native-mmkv": "^3.2.0",
"react-native-modal": "^14.0.0-rc.1",
"react-native-reanimated": "~4.1.1",
@@ -27309,9 +27309,9 @@
}
},
"node_modules/react-native-keyboard-controller": {
- "version": "1.18.5",
- "resolved": "https://registry.npmjs.org/react-native-keyboard-controller/-/react-native-keyboard-controller-1.18.5.tgz",
- "integrity": "sha512-wbYN6Tcu3G5a05dhRYBgjgd74KqoYWuUmroLpigRg9cXy5uYo7prTMIvMgvLtARQtUF7BOtFggUnzgoBOgk0TQ==",
+ "version": "1.21.8",
+ "resolved": "https://registry.npmjs.org/react-native-keyboard-controller/-/react-native-keyboard-controller-1.21.8.tgz",
+ "integrity": "sha512-fPpRb1DkG0mgjNdsVvwKTeEqbTdUymZ7ZEqe5kXPEhEjnvo+3BX3p4CBhg3dEzfonL/hGGSS1dBDMDjiQbAkBQ==",
"license": "MIT",
"dependencies": {
"react-native-is-edge-to-edge": "^1.2.1"
diff --git a/package.json b/package.json
index ce71fd6..a5b795e 100644
--- a/package.json
+++ b/package.json
@@ -78,7 +78,7 @@
"react-native-compressor": "^1.12.0",
"react-native-extended-stylesheet": "^0.12.0",
"react-native-gesture-handler": "~2.28.0",
- "react-native-keyboard-controller": "1.18.5",
+ "react-native-keyboard-controller": "1.21.8",
"react-native-markdown-display": "^7.0.2",
"react-native-mathjax-svg": "^0.9.9",
"react-native-mmkv": "^3.2.0",