Skip to content

Commit 907f020

Browse files
authored
Merge pull request #51 from RonasIT/production
Production
2 parents b2e700c + f6a2b3e commit 907f020

35 files changed

Lines changed: 349 additions & 114 deletions

File tree

apps/mobile/app.config.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ const createConfig = (): Omit<ExpoConfig, 'extra'> & { extra: { eas: EASConfig }
2727
slug: process.env.EXPO_PUBLIC_APP_SLUG as string,
2828
scheme: process.env.EXPO_PUBLIC_APP_SCHEME as string,
2929
owner: process.env.EXPO_PUBLIC_APP_OWNER as string,
30-
version: '1.2.0',
30+
version: '1.3.0',
3131
orientation: 'portrait',
3232
icon: './assets/icon.png',
33-
runtimeVersion: '1.2.0',
33+
runtimeVersion: '1.3.0',
3434
experiments: {
3535
reactCompiler: true,
3636
},
@@ -42,7 +42,7 @@ const createConfig = (): Omit<ExpoConfig, 'extra'> & { extra: { eas: EASConfig }
4242
supportsTablet: false,
4343
buildNumber: appEnv.select({
4444
default: '18',
45-
production: '8',
45+
production: '10',
4646
}),
4747
config: {
4848
usesNonExemptEncryption: false,
@@ -52,7 +52,7 @@ const createConfig = (): Omit<ExpoConfig, 'extra'> & { extra: { eas: EASConfig }
5252
package: appId,
5353
versionCode: appEnv.select({
5454
default: 15,
55-
production: 8,
55+
production: 10,
5656
}),
5757
adaptiveIcon: {
5858
foregroundImage: './assets/adaptive-icon.png',

apps/mobile/app/(main)/chat/create.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export default function CreateChatScreen(): ReactElement {
4747
header: <AppHeader title={translate('TEXT_NEW_CHAT')} onGoBack={handleBackPress} />,
4848
}}
4949
safeAreaProps={{ edges: [] }}
50-
keyBoardAvoidingProps={{ enabled: !isBottomSheetInputFocused }}>
50+
keyBoardAvoidingProps={{ enabled: !isBottomSheetInputFocused, bottomOffset: 60 }}>
5151
<NoConnectionBanner isVisible={isOfflineMode} />
5252
<CreateChat
5353
onChatCreated={handleChatCreated}

libs/mobile/chat/features/ai-message-actions/src/lib/component.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ interface AiMessageActionsProps {
1919
onAddDetails: (messageId: string) => void;
2020
onMoreConcise: (messageId: string) => void;
2121
isLast: boolean;
22+
isResponseGenerating: boolean;
2223
}
2324

2425
//TODO Extend with more actions - https://www.figma.com/design/YPCZjyVlD86psDwUxvMVBc/OpenWebUI-Redesign-React-Native?node-id=27540-25291&t=kg2yUIDp3UQDStLf-0
@@ -31,6 +32,7 @@ export function AiMessageActions({
3132
onAddDetails,
3233
onMoreConcise,
3334
isLast,
35+
isResponseGenerating,
3436
children,
3537
}: PropsWithChildren<AiMessageActionsProps>): ReactElement {
3638
const translate = useTranslation('CHAT.AI_MESSAGE_ACTIONS');
@@ -134,7 +136,10 @@ export function AiMessageActions({
134136

135137
return (
136138
<View>
137-
<MessageActionsSheetWrapper actions={actions} sheetRef={actionsSheetRef}>
139+
<MessageActionsSheetWrapper
140+
actions={actions}
141+
sheetRef={actionsSheetRef}
142+
isResponseGenerating={isResponseGenerating}>
138143
{children}
139144
</MessageActionsSheetWrapper>
140145
<ActionsBottomSheet

libs/mobile/chat/features/archived-chat-item/src/lib/component.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ import { BottomSheetModal } from '@gorhom/bottom-sheet';
22
import { useTranslation } from '@ronas-it/react-native-common-modules/i18n';
33
import { compact } from 'lodash-es';
44
import { Fragment, ReactElement, useRef } from 'react';
5+
import { DownloadChatOptionsSheet } from '@open-webui-react-native/mobile/shared/features/download-chat-options-sheet';
56
import { ChatListRow, ChatListRowProps } from '@open-webui-react-native/mobile/shared/ui/chat-list-row';
67
import { ActionsBottomSheet, ActionSheetItemProps } from '@open-webui-react-native/mobile/shared/ui/ui-kit';
78
import { chatApi, ChatListItem } from '@open-webui-react-native/shared/data-access/api';
89
import { withOfflineGuard } from '@open-webui-react-native/shared/features/network';
910
import { alertService } from '@open-webui-react-native/shared/utils/alert-service';
1011
import { FeatureID, isFeatureEnabled } from '@open-webui-react-native/shared/utils/feature-flag';
11-
import { ToastService } from '@open-webui-react-native/shared/utils/toast-service';
1212

1313
interface ArchivedChatItemProps extends Partial<ChatListRowProps> {
1414
onItemPress: (id: string) => void;
@@ -19,6 +19,7 @@ export function ArchivedChatItem({ item, onItemPress, ...restProps }: ArchivedCh
1919
const translate = useTranslation('CHAT.ARCHIVED_CHATS_LIST.CHAT_ITEM');
2020

2121
const actionsSheetRef = useRef<BottomSheetModal>(null);
22+
const downloadOptionsModalRef = useRef<BottomSheetModal>(null);
2223

2324
const { mutateAsync: deleteChat, isPending: isDeleting } = chatApi.useDelete();
2425
const { mutateAsync: unarchiveChat, isPending: isUnarchiving } = chatApi.useUnarchiveChat();
@@ -46,7 +47,8 @@ export function ArchivedChatItem({ item, onItemPress, ...restProps }: ArchivedCh
4647
await unarchiveChat(item.id);
4748
actionsSheetRef.current?.close();
4849
};
49-
const handleExportChatPress = (): void => ToastService.showFeatureNotImplemented();
50+
51+
const handleExportChatPress = (): void => downloadOptionsModalRef.current?.present();
5052

5153
const actions: Array<ActionSheetItemProps> = compact([
5254
{
@@ -80,6 +82,7 @@ export function ArchivedChatItem({ item, onItemPress, ...restProps }: ArchivedCh
8082
{...restProps}
8183
/>
8284
<ActionsBottomSheet actions={actions} ref={actionsSheetRef} />
85+
<DownloadChatOptionsSheet ref={downloadOptionsModalRef} chatId={item.id} />
8386
</Fragment>
8487
);
8588
}

libs/mobile/chat/features/archived-chats-list/src/lib/components/archived-chats-actions-sheet/component.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ interface ArchivedChatsActionsSheetProps {
1919
export function ArchivedChatsActionsSheet({ renderTrigger }: ArchivedChatsActionsSheetProps): ReactElement {
2020
const translate = useTranslation('CHAT.ARCHIVED_CHATS_LIST.ARCHIVED_CHATS_ACTIONS_SHEET');
2121

22-
const actionsHSeetRef = useRef<BottomSheetModal>(null);
22+
const actionsSheetRef = useRef<BottomSheetModal>(null);
2323

2424
const { unarchiveAllChats, isUnarchiving: isUnarchivingAllChats } = useUnarchiveChats();
2525

@@ -35,12 +35,12 @@ export function ArchivedChatsActionsSheet({ renderTrigger }: ArchivedChatsAction
3535

3636
const handleConfirmUnarchiveAll = async (): Promise<void> => {
3737
await unarchiveAllChats();
38-
actionsHSeetRef.current?.close();
38+
actionsSheetRef.current?.close();
3939
};
4040

4141
const handleExportArchivedChats = async (): Promise<void> => {
4242
await exportArchivedChats();
43-
actionsHSeetRef.current?.close();
43+
actionsSheetRef.current?.close();
4444
};
4545

4646
const actions: Array<ActionSheetItemProps> = compact([
@@ -61,5 +61,5 @@ export function ArchivedChatsActionsSheet({ renderTrigger }: ArchivedChatsAction
6161
return <ActionsBottomSheet
6262
actions={actions}
6363
renderTrigger={renderTrigger}
64-
ref={actionsHSeetRef} />;
64+
ref={actionsSheetRef} />;
6565
}

libs/mobile/chat/features/chat/src/lib/components/ai-message/component.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,14 @@ export function ChatAiMessage({
118118
visible={isPreviewVisible}
119119
onClosePress={handleCloseImagePress}
120120
/>
121-
<MessageVersionControls
122-
message={message}
123-
onNextSibling={onNextSibling}
124-
onPreviousSibling={onPreviousSibling}
125-
getSiblingsInfo={getSiblingsInfo}
126-
/>
121+
{message.parentId && (
122+
<MessageVersionControls
123+
message={message}
124+
onNextSibling={onNextSibling}
125+
onPreviousSibling={onPreviousSibling}
126+
getSiblingsInfo={getSiblingsInfo}
127+
/>
128+
)}
127129
</Fragment>
128130
) : (
129131
<SkeletonMessage />

libs/mobile/chat/features/chat/src/lib/components/messages-list/component.tsx

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { FlashList } from '@shopify/flash-list';
22
import { useLocalSearchParams } from 'expo-router';
33
import { delay } from 'lodash-es';
4-
import React, { ReactElement, useCallback, useRef, useState } from 'react';
5-
import { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';
4+
import React, { ReactElement, useCallback, useRef } from 'react';
5+
import { GestureResponderEvent, NativeScrollEvent, NativeSyntheticEvent } from 'react-native';
66
import { useSharedValue, withTiming } from 'react-native-reanimated';
77
import { AiMessageActions } from '@open-webui-react-native/mobile/chat/features/ai-message-actions';
88
import { useManageMessageSiblings } from '@open-webui-react-native/mobile/chat/features/use-manage-messages-siblings';
@@ -62,7 +62,8 @@ export default function ChatMessagesList({
6262
const isScrollToBottomAvailableTimeout = useRef<NodeJS.Timeout | null | number>(null); //NOTE: number needs to fix pipeline lint error
6363
const isScrollToBottomVisible = useSharedValue(0);
6464
const previousScrollY = useRef(0);
65-
const [autoscrollToBottomThreshold, setAutoscrollToBottomThreshold] = useState<number | undefined>(1);
65+
const shouldAutoscrollToBottomRef = useRef(true);
66+
const previousTouchY = useRef(0);
6667

6768
const { showPreviousSibling, showNextSibling, getSiblingsInfo } = useManageMessageSiblings(chatId, history);
6869
const { mutate: completeChat } = chatApi.useCompleteChat();
@@ -80,6 +81,12 @@ export default function ChatMessagesList({
8081
isScrollToBottomAvailable.current = true;
8182
}, 500);
8283

84+
if (shouldAutoscrollToBottomRef.current) {
85+
requestAnimationFrame(() => {
86+
listRef.current?.scrollToEnd({ animated: true });
87+
});
88+
}
89+
8390
if (!isMessagesListLoaded && listRef.current && messages?.length > 0) {
8491
delay(() => {
8592
listRef.current?.scrollToIndex({
@@ -120,6 +127,7 @@ export default function ChatMessagesList({
120127
//NOTE: Needs to hide scroll to bottom button to avoid its jumping while scrolling to bottom
121128
animateScrollToBottom(0);
122129
isScrollToBottomAvailable.current = false;
130+
123131
delay(() => {
124132
isScrollToBottomAvailable.current = true;
125133
}, 1000);
@@ -128,7 +136,6 @@ export default function ChatMessagesList({
128136
};
129137

130138
const handleEditPress = (index: number, messageId: string, content: string): void => {
131-
setAutoscrollToBottomThreshold(undefined);
132139
onEditPress(messageId, content);
133140
delay(() => {
134141
listRef.current?.scrollToIndex({
@@ -137,9 +144,6 @@ export default function ChatMessagesList({
137144
animated: true,
138145
});
139146
}, 500);
140-
delay(() => {
141-
setAutoscrollToBottomThreshold(1);
142-
}, 1000);
143147
};
144148

145149
const handleContinueResponsePress = (messageId: string): void => {
@@ -171,6 +175,23 @@ export default function ChatMessagesList({
171175
onFollowUpPress(text);
172176
};
173177

178+
const handleTouchStart = (e: GestureResponderEvent): void => {
179+
if (!isResponseGenerating) return;
180+
181+
shouldAutoscrollToBottomRef.current = false;
182+
previousTouchY.current = e.nativeEvent.pageY;
183+
};
184+
185+
const handleTouchMove = (e: GestureResponderEvent): void => {
186+
if (!isResponseGenerating) return;
187+
188+
const { pageY } = e.nativeEvent;
189+
const deltaY = pageY - previousTouchY.current;
190+
191+
previousTouchY.current = pageY;
192+
shouldAutoscrollToBottomRef.current = deltaY < 0;
193+
};
194+
174195
const renderItem = useCallback(
175196
({ item, index }: { item: Message; index: number }) => {
176197
const message = history?.messages[item.id];
@@ -191,6 +212,7 @@ export default function ChatMessagesList({
191212
onTryAgain={onTryAgain}
192213
onAddDetails={onAddDetails}
193214
onMoreConcise={onMoreConcise}
215+
isResponseGenerating={isResponseGenerating}
194216
isLast={isLast}>
195217
<ChatAiMessage
196218
message={message}
@@ -243,14 +265,13 @@ export default function ChatMessagesList({
243265
ItemSeparatorComponent={() => <View className='h-20' />}
244266
data={messages}
245267
renderItem={renderItem}
246-
// TODO: Add autoscrollToBottom logic when it implemented in lib
247268
maintainVisibleContentPosition={{
248269
startRenderingFromBottom: true,
249-
animateAutoScrollToBottom: true,
250-
autoscrollToBottomThreshold,
251270
}}
252271
onContentSizeChange={handleContentSizeChange}
253272
onScroll={handleScroll}
273+
onTouchStart={handleTouchStart}
274+
onTouchMove={handleTouchMove}
254275
scrollEventThrottle={16}
255276
/>
256277
<ChatBottomButton isVisible={isScrollToBottomVisible} onPress={scrollToBottom} />

libs/mobile/chat/features/voice-mode-modal/src/lib/component.tsx

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -184,31 +184,33 @@ export function VoiceModeModal({ onChatCreated, ref, ...props }: VoiceModeModalP
184184
backdropTransitionOutTiming={1}
185185
animationOutTiming={1}
186186
animationIn='fadeIn'
187-
style={{ overflow: 'hidden' }}
187+
style={{ overflow: 'hidden', margin: 0 }}
188188
{...props}>
189-
<AppSafeAreaView edges={['bottom']} className='flex-1'>
190-
<View className='flex-1 items-center justify-center'>
191-
{isThinking || isAiSpeaking ? <Loader /> : <SpeechListener metering={metering} />}
192-
</View>
193-
<View className='flex-row justify-between items-center p-12'>
194-
<IconButton
195-
iconName='camera'
196-
onPress={showUnderConstruction}
197-
className='w-40 h-40 bg-background-secondary rounded-full'
198-
/>
199-
<AppText className='text-sm-sm sm:text-sm'>
200-
{isAiSpeaking
201-
? translate('TEXT_TALKING')
202-
: isThinking
203-
? translate('TEXT_THINKING')
204-
: translate('TEXT_LISTENING')}
205-
</AppText>
206-
<IconButton
207-
iconName='close'
208-
onPress={close}
209-
className='w-40 h-40 bg-background-secondary rounded-full' />
210-
</View>
211-
</AppSafeAreaView>
189+
<View className='flex-1 bg-background-primary'>
190+
<AppSafeAreaView edges={['bottom']} className='flex-1'>
191+
<View className='flex-1 items-center justify-center'>
192+
{isThinking || isAiSpeaking ? <Loader /> : <SpeechListener metering={metering} />}
193+
</View>
194+
<View className='flex-row justify-between items-center p-24'>
195+
<IconButton
196+
iconName='camera'
197+
onPress={showUnderConstruction}
198+
className='w-40 h-40 bg-background-secondary rounded-full'
199+
/>
200+
<AppText className='text-sm-sm sm:text-sm'>
201+
{isAiSpeaking
202+
? translate('TEXT_TALKING')
203+
: isThinking
204+
? translate('TEXT_THINKING')
205+
: translate('TEXT_LISTENING')}
206+
</AppText>
207+
<IconButton
208+
iconName='close'
209+
onPress={close}
210+
className='w-40 h-40 bg-background-secondary rounded-full' />
211+
</View>
212+
</AppSafeAreaView>
213+
</View>
212214
<AppToast />
213215
</Modal>
214216
);

libs/mobile/chat/ui/message-actions-wrapper/src/lib/component.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,23 @@ import {
99
import { useAnimateMessage } from './hooks/use-animate-message';
1010

1111
interface MessageActionsSheetWrapperProps {
12-
sheetRef?: React.RefObject<BottomSheetModal | null>;
1312
actions: Array<ActionSheetItemProps>;
13+
isResponseGenerating?: boolean;
14+
sheetRef?: React.RefObject<BottomSheetModal | null>;
1415
}
1516

1617
export function MessageActionsSheetWrapper({
1718
sheetRef,
1819
actions,
20+
isResponseGenerating,
1921
children,
2022
}: PropsWithChildren<MessageActionsSheetWrapperProps>): ReactElement {
2123
const actionsSheetRef = useRef<BottomSheetModal>(null);
2224
const { animatedStyle, startAnimation, stopAnimation } = useAnimateMessage();
2325

2426
const handleLongPress = (): void => {
27+
if (isResponseGenerating) return;
28+
2529
startAnimation();
2630
actionsSheetRef.current?.present();
2731
};

libs/mobile/shared/features/chat-actions-menu-sheet/src/lib/component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
UpsertFolderSheet,
1212
UpsertFolderSheetMethods,
1313
} from '@open-webui-react-native/mobile/folder/features/upsert-folder-sheet';
14+
import { DownloadChatOptionsSheet } from '@open-webui-react-native/mobile/shared/features/download-chat-options-sheet';
1415
import {
1516
ActionButtonsModal,
1617
ActionButtonsModalMethods,
@@ -31,7 +32,6 @@ import {
3132
import { withOfflineGuard } from '@open-webui-react-native/shared/features/network';
3233
import { alertService } from '@open-webui-react-native/shared/utils/alert-service';
3334
import { FeatureID, isFeatureEnabled } from '@open-webui-react-native/shared/utils/feature-flag';
34-
import { DownloadChatOptionsSheet } from './components';
3535
import { ChatAction } from './enums';
3636

3737
export type ChatActionsMenuSheetMethods = {

0 commit comments

Comments
 (0)