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 logo + +# Open MobileUI + ![License](https://img.shields.io/badge/license-GPL%20v3-blue.svg) ![Platform](https://img.shields.io/badge/platform-iOS%20%7C%20Android-lightgrey.svg) ![React Native](https://img.shields.io/badge/React%20Native-0.79-blue.svg) @@ -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) + +
+ + + Download on the App Store + +   + + Get it on Google Play +
@@ -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",