Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions apps/mobile/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ const createConfig = (): Omit<ExpoConfig, 'extra'> & { extra: { eas: EASConfig }
slug: process.env.EXPO_PUBLIC_APP_SLUG as string,
scheme: process.env.EXPO_PUBLIC_APP_SCHEME as string,
owner: process.env.EXPO_PUBLIC_APP_OWNER as string,
version: '1.5.0',
version: '1.6.4',
userInterfaceStyle: 'automatic',
orientation: 'portrait',
icon: './assets/icon.png',
runtimeVersion: '1.5.0',
runtimeVersion: '1.6.4',
experiments: {
reactCompiler: true,
},
Expand All @@ -46,7 +46,7 @@ const createConfig = (): Omit<ExpoConfig, 'extra'> & { extra: { eas: EASConfig }
supportsTablet: false,
buildNumber: appEnv.select({
default: '18',
production: '24',
production: '29',
}),
config: {
usesNonExemptEncryption: false,
Expand All @@ -56,7 +56,7 @@ const createConfig = (): Omit<ExpoConfig, 'extra'> & { extra: { eas: EASConfig }
package: appId,
versionCode: appEnv.select({
default: 15,
production: 24,
production: 29,
}),
adaptiveIcon: {
foregroundImage: './assets/adaptive-icon.png',
Expand Down
1 change: 1 addition & 0 deletions i18n/mobile/shared/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"TEXT_RENAME": "Rename",
"TEXT_CLONE": "Clone",
"TEXT_ARCHIVE": "Archive",
"TEXT_RESTORE": "Restore",
"TEXT_SHARE": "Share",
"TEXT_DOWNLOAD": "Download",
"TEXT_DELETE": "Delete",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ import { EmailFormSchema } from './forms';

interface EmailSignInFormProps {
onSuccess: () => void;
onApiUrlChange?: (url: string) => void;
setOauthProviders: (providers: Array<Provider>) => void;
}

export function EmailSignInForm({ onSuccess, setOauthProviders }: EmailSignInFormProps): ReactElement {
export function EmailSignInForm({ onSuccess, onApiUrlChange, setOauthProviders }: EmailSignInFormProps): ReactElement {
const translate = useTranslation('AUTH.SIGN_IN.EMAIL_FORM');
const emailRef = useRef<TextInput>(null);
const passwordRef = useRef<TextInput>(null);
Expand Down Expand Up @@ -59,6 +60,7 @@ export function EmailSignInForm({ onSuccess, setOauthProviders }: EmailSignInFor

useEffect(() => {
setValue('url', query, { shouldValidate: true });
onApiUrlChange?.(query);
setOauthProviders([]);
}, [query]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export function OauthWebViewModal({ isVisible, onClose, onGetToken }: OauthWebVi
<AppSafeAreaView edges={['top']} className='flex-1 bg-background-primary'>
<View className='flex-row justify-end px-16 py-12'>
<AppPressable onPress={onClose} hitSlop={12}>
<AppText className='text-body'>{translate('BUTTON_CLOSE')}</AppText>
<AppText>{translate('BUTTON_CLOSE')}</AppText>
</AppPressable>
</View>
<View className='h-full'>
Expand Down
10 changes: 8 additions & 2 deletions libs/mobile/auth/features/sign-in/src/lib/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { EmailSignInForm } from '@open-webui-react-native/mobile/auth/features/e
import { GoogleSignInForm } from '@open-webui-react-native/mobile/auth/features/google-sign-in-form';
import { AppText, View } from '@open-webui-react-native/mobile/shared/ui/ui-kit';
import { Provider } from '@open-webui-react-native/shared/data-access/api';
import { isTestApiUrl } from '@open-webui-react-native/shared/utils/config';
import { ToastService } from '@open-webui-react-native/shared/utils/toast-service';

export interface SignInProps {
Expand All @@ -13,9 +14,10 @@ export interface SignInProps {
export function SignIn(props: SignInProps): ReactElement {
const { onSuccess } = props;
const translate = useTranslation('AUTH.SIGN_IN');
const [apiUrlInput, setApiUrlInput] = useState<string>();
const [providers, setProviders] = useState<Array<Provider>>([]);

const showGoogleSignIn = providers.includes(Provider.GOOGLE);
const showGoogleSignIn = !isTestApiUrl(apiUrlInput) && providers.includes(Provider.GOOGLE);

const handleSuccess = (): void => {
onSuccess();
Expand All @@ -29,7 +31,11 @@ export function SignIn(props: SignInProps): ReactElement {
<View className='mb-12'>
<AppText className='text-h2-sm sm:text-h2 font-medium mb-24'>{translate('TEXT_TITLE_EXTERNAL')}</AppText>
</View>
<EmailSignInForm onSuccess={handleSuccess} setOauthProviders={setProviders} />
<EmailSignInForm
onSuccess={handleSuccess}
onApiUrlChange={(url) => setApiUrlInput(url)}
setOauthProviders={setProviders}
/>
{showGoogleSignIn && (
<View className='pt-40'>
<GoogleSignInForm onSuccess={handleSuccess} />
Expand Down
4 changes: 4 additions & 0 deletions libs/mobile/chat/features/chat/src/lib/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export function Chat({ chatId, selectedModelId, isNewChat, resetToChatsList }: C
const [isMessagesListLoaded, setIsMessagesListLoaded] = useState(false);
const [isChatVisible, setIsChatVisible] = useState(false);
const [activeInputMode, setActiveInputMode] = useState<ActiveInputMode | null>(null);
const [inputRerenderKey, setInputRerenderKey] = useState(0);

const {
attachedFiles,
Expand Down Expand Up @@ -164,6 +165,8 @@ export function Chat({ chatId, selectedModelId, isNewChat, resetToChatsList }: C
sendMessage(inputValue, selectedModelId, options, attachedFiles.get(), attachedImages.get());
reset();
resetAttachments();
// NOTE: Forces input rerender to reset it to its initial height after submit
setInputRerenderKey((key) => key + 1);
})();

const handleFollowUpPress = (text: string): void => {
Expand Down Expand Up @@ -257,6 +260,7 @@ export function Chat({ chatId, selectedModelId, isNewChat, resetToChatsList }: C
onDeleteImagePress={handleDeleteImage}
modelId={selectedModelId}
isResponseGenerating={isResponseGenerating}
inputRerenderKey={inputRerenderKey}
chat={chat}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default function ChatBottomButton({ isVisible, onPress }: ChatBottomButto

const animatedStyle = useAnimatedStyle(() => ({
transform: [
{ translateY: keyboardHeight.value ? keyboardHeight.value + 15 : 0 },
{ translateY: keyboardHeight.value ? keyboardHeight.value + 4 : -15 },
{ scale: interpolate(isVisible.value, [0, 1], [0, 1]) },
],
}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { delay } from 'lodash-es';
import React, { ReactElement, useCallback, useRef } from 'react';
import { GestureResponderEvent, NativeScrollEvent, NativeSyntheticEvent, ScrollViewProps } from 'react-native';
import { useSharedValue, withTiming } from 'react-native-reanimated';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { AiMessageActions } from '@open-webui-react-native/mobile/chat/features/ai-message-actions';
import { useManageMessageSiblings } from '@open-webui-react-native/mobile/chat/features/use-manage-messages-siblings';
import { UserMessageActions } from '@open-webui-react-native/mobile/chat/features/user-message-actions';
Expand Down Expand Up @@ -65,6 +66,8 @@ export default function ChatMessagesList({
const shouldAutoscrollToBottomRef = useRef(true);
const previousTouchY = useRef(0);

const { bottom } = useSafeAreaInsets();

const { showPreviousSibling, showNextSibling, getSiblingsInfo } = useManageMessageSiblings(chatId, history);
const { mutate: completeChat } = chatApi.useCompleteChat();
const { id }: ChatScreenParams = useLocalSearchParams();
Expand Down Expand Up @@ -259,7 +262,8 @@ export default function ChatMessagesList({
<View className='relative flex-1'>
<AppFlashList<Message>
ref={listRef}
contentContainerClassName='pb-[135] px-16'
contentContainerClassName='px-16'
contentContainerStyle={{ paddingBottom: bottom + 120 }}
showsVerticalScrollIndicator={false}
drawDistance={1500} //NOTE: Needs to avoid image jumping (while rerendering) when scrolling
keyExtractor={(item) => item.id}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ interface FormChatInputProps<T extends FieldValues> extends AppInputProps {
isLoading?: boolean;
isSuggestionShown?: boolean;
isResponseGenerating?: boolean;
inputRerenderKey?: number;
}

export interface FormChatInputSchema {
Expand All @@ -65,6 +66,7 @@ export function FormChatInput<T extends FieldValues>({
isLoading,
isSuggestionShown,
isResponseGenerating,
inputRerenderKey,
...restProps
}: FormChatInputProps<T>): ReactElement {
const translate = useTranslation('CHAT.FORM_CHAT_INPUT');
Expand Down Expand Up @@ -150,6 +152,7 @@ export function FormChatInput<T extends FieldValues>({
/>
) : (
<AppTextInput
key={inputRerenderKey}
value={field.value}
onChangeText={field.onChange}
onBlur={field.onBlur}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export function ChatActionsMenuSheet({ goToChat, isPinned, ref, isInChat }: Chat
const { mutateAsync: pinChat, isPending: isPinning } = chatApi.usePinChat();
const { mutateAsync: cloneChat, isPending: isCloning } = chatApi.useCloneChat();
const { mutateAsync: archiveChat, isPending: isArchiving } = chatApi.useArchiveChat();
const { mutateAsync: unarchiveChat, isPending: isUnarchiving } = chatApi.useUnarchiveChat();
const { data: folders } = foldersApi.useGetFolders();

const [activeChat, setActiveChat] = useState<ChatListItem | null>(null);
Expand Down Expand Up @@ -94,6 +95,8 @@ export function ChatActionsMenuSheet({ goToChat, isPinned, ref, isInChat }: Chat
const chatTitle = activeChat?.title ?? '';
const { data: chatFullData } = chatApi.useGet(chatId, { enabled: !!chatId });

const isArchived = chatFullData?.archived;

const openCreateFolderModal = (): void => {
upsertFolderSheetRef.current?.present();
};
Expand Down Expand Up @@ -126,6 +129,9 @@ export function ChatActionsMenuSheet({ goToChat, isPinned, ref, isInChat }: Chat
case ChatAction.ARCHIVE:
await archiveChatHandler();
break;
case ChatAction.RESTORE:
await restoreChatHandler();
break;
case ChatAction.DELETE:
await onDeleteConfirm();
break;
Expand Down Expand Up @@ -215,6 +221,11 @@ export function ChatActionsMenuSheet({ goToChat, isPinned, ref, isInChat }: Chat
closeActionsModal();
};

const restoreChatHandler = async (): Promise<void> => {
await unarchiveChat(chatId);
closeActionsModal();
};

const onFolderSelectedHandler = async (id: string | null): Promise<void> => {
await updateChatFolder({
id: chatId,
Expand Down Expand Up @@ -244,10 +255,10 @@ export function ChatActionsMenuSheet({ goToChat, isPinned, ref, isInChat }: Chat
onPress: () => handleAction(ChatAction.CLONE),
},
isFeatureEnabled(FeatureID.ARCHIVE_CHAT) && {
title: translate('TEXT_ARCHIVE'),
iconName: 'archive',
isLoading: isArchiving,
onPress: () => handleAction(ChatAction.ARCHIVE),
title: isArchived ? translate('TEXT_RESTORE') : translate('TEXT_ARCHIVE'),
iconName: isArchived ? 'unarchive' : 'archive',
isLoading: isArchived ? isUnarchiving : isArchiving,
onPress: () => handleAction(isArchived ? ChatAction.RESTORE : ChatAction.ARCHIVE),
},
{ title: translate('TEXT_SHARE'), iconName: 'exportIcon', onPress: openShareChatModal },
{ title: translate('TEXT_DOWNLOAD'), iconName: 'download', onPress: openDownloadOptionsModal },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export enum ChatAction {
RENAME = 'rename',
CLONE = 'clone',
ARCHIVE = 'archive',
RESTORE = 'restore',
DELETE = 'delete',
CLOSE = 'close',
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getApiUrl } from '@open-webui-react-native/shared/utils/config';
import { getDisplayApiUrl } from '@open-webui-react-native/shared/utils/config';

export function getShareChatLink(shareId: string): string {
return `${getApiUrl()}/s/${shareId}`;
return `${getDisplayApiUrl()}/s/${shareId}`;
}
15 changes: 11 additions & 4 deletions libs/shared/utils/config/src/get-api-url.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// eslint-disable-next-line @nx/enforce-module-boundaries
import { appStorageService } from '@open-webui-react-native/shared/data-access/storage';
import { appEnv } from '@open-webui-react-native/shared/utils/app-env';

Expand All @@ -8,19 +8,26 @@ export const ronasApiUrl = appEnv.select({
production: 'https://ai.ronas.online',
});

const testApiUrl = 'https://ai.test-api.online';
export const testApiUrl = 'https://ai.test-api.online';

const normalizeUrl = (url?: string): string => (url ?? '').trim().replace(/\/+$/, '');

export const resolveApiUrl = (url: string): string => {
return normalizeUrl(url) === normalizeUrl(testApiUrl) ? normalizeUrl(ronasApiUrl) : normalizeUrl(url);
};

export const getApiUrl = (): string => {
export const isTestApiUrl = (url?: string): boolean =>
normalizeUrl(url ?? appStorageService.apiUrl.get()) === normalizeUrl(testApiUrl);

export const getDisplayApiUrl = (): string => {
const stored = normalizeUrl(appStorageService.apiUrl.get());
const fallback = normalizeUrl(ronasApiUrl);

return resolveApiUrl(stored || fallback);
return stored || fallback;
};

export const getApiUrl = (): string => {
return resolveApiUrl(getDisplayApiUrl());
};

export const getHost = (url: string): string =>
Expand Down
Loading