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
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { BottomSheetModal } from '@gorhom/bottom-sheet';
import { useTranslation } from '@ronas-it/react-native-common-modules/i18n';
import { compact } from 'lodash-es';
import { Fragment, ReactElement, useRef } from 'react';
import { DownloadChatOptionsSheet } from '@open-webui-react-native/mobile/shared/features/download-chat-options-sheet';
import { ChatListRow, ChatListRowProps } from '@open-webui-react-native/mobile/shared/ui/chat-list-row';
import { ActionsBottomSheet, ActionSheetItemProps } from '@open-webui-react-native/mobile/shared/ui/ui-kit';
import { chatApi, ChatListItem } from '@open-webui-react-native/shared/data-access/api';
import { withOfflineGuard } from '@open-webui-react-native/shared/features/network';
import { alertService } from '@open-webui-react-native/shared/utils/alert-service';
import { FeatureID, isFeatureEnabled } from '@open-webui-react-native/shared/utils/feature-flag';
import { ToastService } from '@open-webui-react-native/shared/utils/toast-service';

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

const actionsSheetRef = useRef<BottomSheetModal>(null);
const downloadOptionsModalRef = useRef<BottomSheetModal>(null);

const { mutateAsync: deleteChat, isPending: isDeleting } = chatApi.useDelete();
const { mutateAsync: unarchiveChat, isPending: isUnarchiving } = chatApi.useUnarchiveChat();
Expand Down Expand Up @@ -46,7 +47,8 @@ export function ArchivedChatItem({ item, onItemPress, ...restProps }: ArchivedCh
await unarchiveChat(item.id);
actionsSheetRef.current?.close();
};
const handleExportChatPress = (): void => ToastService.showFeatureNotImplemented();

const handleExportChatPress = (): void => downloadOptionsModalRef.current?.present();

const actions: Array<ActionSheetItemProps> = compact([
{
Expand Down Expand Up @@ -80,6 +82,7 @@ export function ArchivedChatItem({ item, onItemPress, ...restProps }: ArchivedCh
{...restProps}
/>
<ActionsBottomSheet actions={actions} ref={actionsSheetRef} />
<DownloadChatOptionsSheet ref={downloadOptionsModalRef} chatId={item.id} />
</Fragment>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ interface ArchivedChatsActionsSheetProps {
export function ArchivedChatsActionsSheet({ renderTrigger }: ArchivedChatsActionsSheetProps): ReactElement {
const translate = useTranslation('CHAT.ARCHIVED_CHATS_LIST.ARCHIVED_CHATS_ACTIONS_SHEET');

const actionsHSeetRef = useRef<BottomSheetModal>(null);
const actionsSheetRef = useRef<BottomSheetModal>(null);

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

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

const handleConfirmUnarchiveAll = async (): Promise<void> => {
await unarchiveAllChats();
actionsHSeetRef.current?.close();
actionsSheetRef.current?.close();
};

const handleExportArchivedChats = async (): Promise<void> => {
await exportArchivedChats();
actionsHSeetRef.current?.close();
actionsSheetRef.current?.close();
};

const actions: Array<ActionSheetItemProps> = compact([
Expand All @@ -61,5 +61,5 @@ export function ArchivedChatsActionsSheet({ renderTrigger }: ArchivedChatsAction
return <ActionsBottomSheet
actions={actions}
renderTrigger={renderTrigger}
ref={actionsHSeetRef} />;
ref={actionsSheetRef} />;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
UpsertFolderSheet,
UpsertFolderSheetMethods,
} from '@open-webui-react-native/mobile/folder/features/upsert-folder-sheet';
import { DownloadChatOptionsSheet } from '@open-webui-react-native/mobile/shared/features/download-chat-options-sheet';
import {
ActionButtonsModal,
ActionButtonsModalMethods,
Expand All @@ -31,7 +32,6 @@ import {
import { withOfflineGuard } from '@open-webui-react-native/shared/features/network';
import { alertService } from '@open-webui-react-native/shared/utils/alert-service';
import { FeatureID, isFeatureEnabled } from '@open-webui-react-native/shared/utils/feature-flag';
import { DownloadChatOptionsSheet } from './components';
import { ChatAction } from './enums';

export type ChatActionsMenuSheetMethods = {
Expand Down

This file was deleted.

12 changes: 12 additions & 0 deletions libs/mobile/shared/features/download-chat-options-sheet/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# mobile/shared/features/download-chat-options-sheet

This library was generated with [Nx](https://nx.dev).

## Running unit tests

Run `nx test mobile/shared/features/download-chat-options-sheet` to execute the unit tests via [Jest](https://jestjs.io).
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const nx = require('@nx/eslint-plugin');
const baseConfig = require('../../../../../eslint.config.cjs');

module.exports = [
...baseConfig,
...nx.configs['flat/react'],
{
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
// Override or add rules here
rules: {},
},
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "mobile/shared/features/download-chat-options-sheet",
"$schema": "../../../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/mobile/shared/features/download-chat-options-sheet/src",
"projectType": "library",
"tags": ["app:mobile", "scope:shared", "type:features"],
"// targets": "to see all targets run: nx show project mobile/shared/features/download-chat-options-sheet --web",
"targets": {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './lib';
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import { BottomSheetModal } from '@gorhom/bottom-sheet';
import { useTranslation } from '@ronas-it/react-native-common-modules/i18n';
import { ReactElement, useState } from 'react';
import {
FileExtension,
fileSystemService,
} from '@open-webui-react-native/mobile/shared/data-access/file-system-service';
import { FileExtension } from '@open-webui-react-native/mobile/shared/data-access/file-system-service';
import { createChatDownloadHandlers } from '@open-webui-react-native/mobile/shared/features/download-chat';
import { ActionsBottomSheet, ActionSheetItemProps } from '@open-webui-react-native/mobile/shared/ui/ui-kit';
import { chatQueriesKeys, ChatResponse } from '@open-webui-react-native/shared/data-access/api';
import { queryClient } from '@open-webui-react-native/shared/data-access/query-client';
import { getChatAsText } from '@open-webui-react-native/shared/features/get-chat-as-text';

export interface DownloadChatOptionsSheetProps {
chatId: string;
Expand All @@ -22,37 +17,23 @@ export function DownloadChatOptionsSheet({ chatId, ref }: DownloadChatOptionsShe
FileExtension.JSON | FileExtension.TXT | FileExtension.PDF | null
>(null);

const getChat = async (): Promise<ChatResponse> =>
await queryClient.fetchQuery<ChatResponse>({ queryKey: chatQueriesKeys.get(chatId).queryKey });

const onDownloadText = async (): Promise<void> => {
setFileTypeLoading(FileExtension.TXT);
const { chat } = await getChat();
const text = getChatAsText(chat);
await fileSystemService.shareTextFile(`chat-${chat.title}`, text);
setFileTypeLoading(null);
};

const onDownloadJson = async (): Promise<void> => {
setFileTypeLoading(FileExtension.JSON);
const { chat } = await getChat();
const jsonData = JSON.stringify([chat], null, 2);
await fileSystemService.shareJsonFile(`chat-export-${Date.now()}`, jsonData);
setFileTypeLoading(null);
};
const { downloadJson, downloadText } = createChatDownloadHandlers({
chatId,
setFileTypeLoading,
});

const actions: Array<ActionSheetItemProps> = [
{
title: translate('TEXT_EXPORT_CHAT_JSON'),
iconName: 'jsonFile',
onPress: onDownloadJson,
onPress: downloadJson,
disabled: !!fileTypeLoading,
isLoading: fileTypeLoading === FileExtension.JSON,
},
{
title: translate('TEXT_PLAIN_TEXT'),
iconName: 'txtFile',
onPress: onDownloadText,
onPress: downloadText,
disabled: !!fileTypeLoading,
isLoading: fileTypeLoading === FileExtension.TXT,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"jsx": "react-jsx",
"allowJs": false,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
}
],
"extends": "../../../../../tsconfig.base.json"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../../../dist/out-tsc",
"types": ["node", "@nx/react/typings/cssmodule.d.ts", "@nx/react/typings/image.d.ts"]
},
"exclude": [
"jest.config.ts",
"src/**/*.spec.ts",
"src/**/*.test.ts",
"src/**/*.spec.tsx",
"src/**/*.test.tsx",
"src/**/*.spec.js",
"src/**/*.test.js",
"src/**/*.spec.jsx",
"src/**/*.test.jsx"
],
"include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
}
12 changes: 12 additions & 0 deletions libs/mobile/shared/features/download-chat/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}
7 changes: 7 additions & 0 deletions libs/mobile/shared/features/download-chat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# mobile/shared/features/download-chat

This library was generated with [Nx](https://nx.dev).

## Running unit tests

Run `nx test mobile/shared/features/download-chat` to execute the unit tests via [Jest](https://jestjs.io).
12 changes: 12 additions & 0 deletions libs/mobile/shared/features/download-chat/eslint.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const nx = require('@nx/eslint-plugin');
const baseConfig = require('../../../../../eslint.config.cjs');

module.exports = [
...baseConfig,
...nx.configs['flat/react'],
{
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
// Override or add rules here
rules: {},
},
];
9 changes: 9 additions & 0 deletions libs/mobile/shared/features/download-chat/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "mobile/shared/features/download-chat",
"$schema": "../../../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/mobile/shared/features/download-chat/src",
"projectType": "library",
"tags": ["app:mobile", "scope:shared", "type:features"],
"// targets": "to see all targets run: nx show project mobile/shared/features/download-chat --web",
"targets": {}
}
55 changes: 55 additions & 0 deletions libs/mobile/shared/features/download-chat/src/download-chat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {
FileExtension,
fileSystemService,
} from '@open-webui-react-native/mobile/shared/data-access/file-system-service';
import { ChatResponse, getChatQueryOptions } from '@open-webui-react-native/shared/data-access/api';
import { queryClient } from '@open-webui-react-native/shared/data-access/query-client';
import { getChatAsText } from '@open-webui-react-native/shared/features/get-chat-as-text';

export interface CreateChatDownloadHandlersParams {
chatId: string;
setFileTypeLoading: (type: FileExtension | null) => void;
}

export interface ChatDownloadHandlers {
downloadJson: () => Promise<void>;
downloadText: () => Promise<void>;
}

export const createChatDownloadHandlers = ({
chatId,
setFileTypeLoading,
}: CreateChatDownloadHandlersParams): ChatDownloadHandlers => {
const getChat = async (): Promise<ChatResponse> => queryClient.ensureQueryData(getChatQueryOptions(chatId));

const downloadJson = async (): Promise<void> => {
try {
setFileTypeLoading(FileExtension.JSON);

const { chat } = await getChat();
const jsonData = JSON.stringify([chat], null, 2);

await fileSystemService.shareJsonFile(`chat-export-${Date.now()}`, jsonData);
} finally {
setFileTypeLoading(null);
}
};

const downloadText = async (): Promise<void> => {
try {
setFileTypeLoading(FileExtension.TXT);

const { chat } = await getChat();
const text = getChatAsText(chat);

await fileSystemService.shareTextFile(`chat-${chat.title}`, text);
} finally {
setFileTypeLoading(null);
}
};

return {
downloadJson,
downloadText,
};
};
1 change: 1 addition & 0 deletions libs/mobile/shared/features/download-chat/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './download-chat';
17 changes: 17 additions & 0 deletions libs/mobile/shared/features/download-chat/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"jsx": "react-jsx",
"allowJs": false,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
}
],
"extends": "../../../../../tsconfig.base.json"
}
19 changes: 19 additions & 0 deletions libs/mobile/shared/features/download-chat/tsconfig.lib.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../../../dist/out-tsc",
"types": ["node", "@nx/react/typings/cssmodule.d.ts", "@nx/react/typings/image.d.ts"]
},
"exclude": [
"jest.config.ts",
"src/**/*.spec.ts",
"src/**/*.test.ts",
"src/**/*.spec.tsx",
"src/**/*.test.tsx",
"src/**/*.spec.js",
"src/**/*.test.js",
"src/**/*.spec.jsx",
"src/**/*.test.jsx"
],
"include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
}
Loading
Loading