diff --git a/react-native/android/app/build.gradle b/react-native/android/app/build.gradle
index dccdc44..f621bfa 100644
--- a/react-native/android/app/build.gradle
+++ b/react-native/android/app/build.gradle
@@ -79,7 +79,7 @@ android {
applicationId "com.aws.swiftchat"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
- versionCode 8
+ versionCode 10
versionName "1.5.0"
ndk {
//noinspection ChromeOsAbiSupport
diff --git a/react-native/ios/SwiftChat.xcodeproj/project.pbxproj b/react-native/ios/SwiftChat.xcodeproj/project.pbxproj
index 16b0aed..86211a4 100644
--- a/react-native/ios/SwiftChat.xcodeproj/project.pbxproj
+++ b/react-native/ios/SwiftChat.xcodeproj/project.pbxproj
@@ -485,7 +485,7 @@
CODE_SIGN_ENTITLEMENTS = SwiftChat/SwiftChat.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 8;
+ CURRENT_PROJECT_VERSION = 10;
DEVELOPMENT_TEAM = BUA6W9H7T3;
ENABLE_BITCODE = NO;
"ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = YES;
@@ -526,7 +526,7 @@
CODE_SIGN_ENTITLEMENTS = SwiftChat/SwiftChat.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 8;
+ CURRENT_PROJECT_VERSION = 10;
DEVELOPMENT_TEAM = BUA6W9H7T3;
"ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = YES;
INFOPLIST_FILE = SwiftChat/Info.plist;
diff --git a/react-native/src/chat/ChatScreen.tsx b/react-native/src/chat/ChatScreen.tsx
index 6923d6c..e859d78 100644
--- a/react-native/src/chat/ChatScreen.tsx
+++ b/react-native/src/chat/ChatScreen.tsx
@@ -201,6 +201,8 @@ function ChatScreen(): React.JSX.Element {
const { id } = event.params;
if (sessionIdRef.current === id) {
sessionIdRef.current = getSessionId() + 1;
+ setUsage(undefined);
+ bedrockMessages.current = [];
clearCachedNode();
setMessages([]);
}
@@ -501,7 +503,9 @@ function ChatScreen(): React.JSX.Element {
/>
)
}
- renderMessage={props => }
+ renderMessage={props => (
+
+ )}
listViewProps={{
contentContainerStyle: styles.contentContainer,
contentInset: { top: 2 },
diff --git a/react-native/src/chat/component/CustomFileListComponent.tsx b/react-native/src/chat/component/CustomFileListComponent.tsx
index 88da348..f9f5dd4 100644
--- a/react-native/src/chat/component/CustomFileListComponent.tsx
+++ b/react-native/src/chat/component/CustomFileListComponent.tsx
@@ -14,6 +14,7 @@ import { ImageSource } from 'react-native-image-viewing/dist/@types';
import Share from 'react-native-share';
import FileViewer from 'react-native-file-viewer';
import { isMac } from '../../App.tsx';
+import { getFullFileUrl } from '../util/FileUtils.ts';
interface CustomFileProps {
files: FileInfo[];
@@ -55,6 +56,7 @@ export const CustomFileListComponent: React.FC = ({
const renderFileItem = (file: FileInfo, fileIndex: number) => {
const isImage = file.type === FileType.image;
+ const fullFileUrl = getFullFileUrl(file.url);
const itemKey = `file-${fileIndex}-${file.url}`;
return (
= ({
try {
const options = {
type: 'text/plain',
- url: file.url,
+ url: fullFileUrl,
showAppsToView: true,
};
Share.open(options).then();
@@ -91,13 +93,13 @@ export const CustomFileListComponent: React.FC = ({
}}
onPress={() => {
if (isMac || file.type === FileType.document) {
- openInFileViewer(file.url);
+ openInFileViewer(fullFileUrl);
} else {
const images = files
.filter(item => item.type === FileType.image)
- .map(item => ({ uri: item.url }));
+ .map(item => ({ uri: getFullFileUrl(item.url) }));
const currentIndex = images.findIndex(
- img => img.uri === file.url
+ img => img.uri === fullFileUrl
);
setImageUrls(images);
setIndex(currentIndex);
@@ -106,7 +108,7 @@ export const CustomFileListComponent: React.FC = ({
}}>
{isImage ? (
diff --git a/react-native/src/chat/component/CustomMessageComponent.tsx b/react-native/src/chat/component/CustomMessageComponent.tsx
index bad67f1..e35dcfe 100644
--- a/react-native/src/chat/component/CustomMessageComponent.tsx
+++ b/react-native/src/chat/component/CustomMessageComponent.tsx
@@ -20,7 +20,7 @@ import { IMessage, MessageProps } from 'react-native-gifted-chat';
import { CustomMarkdownRenderer } from './CustomMarkdownRenderer.tsx';
import { MarkedStyles } from 'react-native-marked/src/theme/types.ts';
import ImageView from 'react-native-image-viewing';
-import { PressMode } from '../../types/Chat.ts';
+import { ChatStatus, PressMode } from '../../types/Chat.ts';
import { trigger } from '../util/HapticUtils.ts';
import { HapticFeedbackTypes } from 'react-native-haptic-feedback/src/types.ts';
import Clipboard from '@react-native-clipboard/clipboard';
@@ -33,8 +33,13 @@ import { isMac } from '../../App.tsx';
import { CustomTokenizer } from './CustomTokenizer.ts';
import { State, TapGestureHandler } from 'react-native-gesture-handler';
-const CustomMessageComponent: React.FC> = ({
+interface CustomMessageProps extends MessageProps {
+ chatStatus: ChatStatus;
+}
+
+const CustomMessageComponent: React.FC = ({
currentMessage,
+ chatStatus,
}) => {
const [visible, setIsVisible] = useState(false);
const [imgUrl, setImgUrl] = useState('');
@@ -79,7 +84,7 @@ const CustomMessageComponent: React.FC> = ({
const customTokenizer = useMemo(() => new CustomTokenizer(), []);
const handleCopy = () => {
if (isEdit) {
- setIsEdit(false);
+ setIsEditValue(false);
return;
}
Clipboard.setString(currentMessage?.text ?? '');
@@ -87,11 +92,17 @@ const CustomMessageComponent: React.FC> = ({
};
const handleEdit = () => {
- setIsEdit(!isEdit);
+ setIsEditValue(!isEdit);
};
const onDoubleTap = () => {
- setIsEdit(true);
+ setIsEditValue(true);
+ };
+
+ const setIsEditValue = (value: boolean) => {
+ if (chatStatus !== ChatStatus.Running) {
+ setIsEdit(value);
+ }
};
useEffect(() => {
diff --git a/react-native/src/chat/util/FileUtils.ts b/react-native/src/chat/util/FileUtils.ts
index 5111828..08c9d2f 100644
--- a/react-native/src/chat/util/FileUtils.ts
+++ b/react-native/src/chat/util/FileUtils.ts
@@ -24,11 +24,12 @@ export const saveFile = async (sourceUrl: string, fileName: string) => {
if (!filesDirExists) {
await RNFS.mkdir(filesDir);
}
- const destinationPath = await getUniqueFileName(filesDir, fileName);
+ const uniqueFileName = await getUniqueFileName(filesDir, fileName);
+ const destinationPath = `${filesDir}/${uniqueFileName}`;
await RNFS.copyFile(sourceUrl, destinationPath);
return Platform.OS === 'android'
? `file://${destinationPath}`
- : destinationPath;
+ : `files/${uniqueFileName}`;
} catch (error) {
console.warn('Error saving file:', error);
}
@@ -37,7 +38,8 @@ export const saveFile = async (sourceUrl: string, fileName: string) => {
export const getFileBytes = async (fileUrl: string) => {
try {
- return await RNFS.readFile(fileUrl, 'base64');
+ const fullFileUrl = getFullFileUrl(fileUrl);
+ return await RNFS.readFile(fullFileUrl, 'base64');
} catch (error) {
console.warn('Error reading image file:', fileUrl, error);
throw error;
@@ -61,7 +63,21 @@ const getUniqueFileName = async (
finalFileName = `${nameWithoutExt}(${counter})${extension}`;
finalPath = `${basePath}/${finalFileName}`;
}
- return finalPath;
+ return finalFileName;
+};
+
+export const getFullFileUrl = (url: string) => {
+ if (Platform.OS === 'android') {
+ return url;
+ } else if (url.startsWith('files/')) {
+ return `${RNFS.DocumentDirectoryPath}/${url}`;
+ } else {
+ return (
+ RNFS.DocumentDirectoryPath +
+ '/files' +
+ url.substring(url.lastIndexOf('/'))
+ );
+ }
};
const MAX_IMAGES = 20;