uploading attachments is working and images are displayed
This commit is contained in:
@@ -54,6 +54,7 @@ export async function getMessages(
|
||||
`/api/chat/messages/${contact}?limit=${limit}&cursor=${cursor}`,
|
||||
);
|
||||
console.log('Get messages response: ', response.data);
|
||||
|
||||
return response.data;
|
||||
} catch (e) {
|
||||
console.error('Failed to get messages: ', e);
|
||||
|
||||
@@ -11,7 +11,7 @@ const nanoid = customAlphabet('1234567890', 5);
|
||||
|
||||
type Input = {
|
||||
message: string;
|
||||
file: FileList | null;
|
||||
attachment: FileList | null;
|
||||
};
|
||||
|
||||
type MessageFormProps = {
|
||||
@@ -24,6 +24,7 @@ const MessageForm = ({ contact, setMessages }: MessageFormProps) => {
|
||||
const { username }: { username: string } = useOutletContext();
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
const [isUploading, setIsUploading] = useState(false);
|
||||
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
||||
|
||||
const { register, handleSubmit, reset, watch, setValue } = useForm<Input>({
|
||||
mode: 'onChange',
|
||||
@@ -66,7 +67,7 @@ const MessageForm = ({ contact, setMessages }: MessageFormProps) => {
|
||||
},
|
||||
);
|
||||
setIsUploading(false);
|
||||
return response.data.attachmentUrl;
|
||||
return response.data;
|
||||
} catch (e) {
|
||||
setIsUploading(false);
|
||||
console.error('Failed to upload attachment: ', e);
|
||||
@@ -83,11 +84,12 @@ const MessageForm = ({ contact, setMessages }: MessageFormProps) => {
|
||||
return;
|
||||
}
|
||||
|
||||
let attachmentUrl: string | null = null;
|
||||
|
||||
let attachmentUrl = null;
|
||||
if (file) {
|
||||
attachmentUrl = await uploadFile(file);
|
||||
if (!attachmentUrl) {
|
||||
const response = await uploadFile(file);
|
||||
if (response?.attachment_url) {
|
||||
attachmentUrl = response.attachment_url;
|
||||
} else {
|
||||
console.error('Failed to upload attachment');
|
||||
return;
|
||||
}
|
||||
@@ -102,7 +104,7 @@ const MessageForm = ({ contact, setMessages }: MessageFormProps) => {
|
||||
message_id: 0, // Set to 0 because of key={msg.message_id || msg.tempId} in messages list
|
||||
pending: true,
|
||||
tempId: tempId,
|
||||
attachment: attachmentUrl || null,
|
||||
attachment_url: attachmentUrl || null,
|
||||
};
|
||||
|
||||
setMessages((prevMessages) => [...prevMessages, tempMessage]); // Display as gray
|
||||
@@ -113,9 +115,14 @@ const MessageForm = ({ contact, setMessages }: MessageFormProps) => {
|
||||
message: data.message.trim(),
|
||||
recipient: contact,
|
||||
tempId: tempId,
|
||||
attachmentUrl: attachmentUrl || undefined,
|
||||
attachment_url: attachmentUrl,
|
||||
},
|
||||
(response: { status: string; message_id: number; tempId: string }) => {
|
||||
(response: {
|
||||
status: string;
|
||||
message_id: number;
|
||||
tempId: number;
|
||||
message: string;
|
||||
}) => {
|
||||
if (response.status === 'ok') {
|
||||
setMessages((prevMessages) =>
|
||||
prevMessages.map((msg) =>
|
||||
@@ -126,10 +133,12 @@ const MessageForm = ({ contact, setMessages }: MessageFormProps) => {
|
||||
);
|
||||
|
||||
reset({ message: '' });
|
||||
setValue('file', null);
|
||||
setValue('attachment', null);
|
||||
setFile(null);
|
||||
}
|
||||
console.log(response.status, response.tempId);
|
||||
console.log(
|
||||
`status: ${response.status}, tempId: ${response.tempId}, message: ${response.message}`,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -137,7 +146,7 @@ const MessageForm = ({ contact, setMessages }: MessageFormProps) => {
|
||||
message: data.message.trim(),
|
||||
recipient: contact,
|
||||
tempId: tempId,
|
||||
attachmentUrl: attachmentUrl,
|
||||
attachment_url: attachmentUrl,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -152,7 +161,7 @@ const MessageForm = ({ contact, setMessages }: MessageFormProps) => {
|
||||
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (e.target.files && e.target.files.length > 0) {
|
||||
setFile(e.target.files[0]);
|
||||
setValue('file', e.target.files); // Update form state with file
|
||||
setValue('attachment', e.target.files); // Update form state with file
|
||||
}
|
||||
};
|
||||
|
||||
@@ -200,13 +209,14 @@ const MessageForm = ({ contact, setMessages }: MessageFormProps) => {
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex gap-2">
|
||||
<input
|
||||
name="attachment"
|
||||
type="file"
|
||||
accept="*/*"
|
||||
onChange={handleFileChange}
|
||||
disabled={isUploading}
|
||||
ref={fileInputRef}
|
||||
/>
|
||||
{isUploading && (
|
||||
<span className="text-gray-500 text-sm">Uploading...</span>
|
||||
|
||||
@@ -125,7 +125,19 @@ function MessagesArea({
|
||||
}`}
|
||||
key={msg.message_id || msg.tempId}
|
||||
>
|
||||
{msg.tempId} {msg.message_id} {msg.sender}: {msg.message}
|
||||
{msg.sender}: {msg.message}
|
||||
{msg.attachment_url ? (
|
||||
<div className="mt-2">
|
||||
<a href={msg.attachment_url}>
|
||||
{' '}
|
||||
<img
|
||||
src={msg.attachment_url}
|
||||
alt="attachment"
|
||||
className="max-w-full max-h-80 object-contain rounded"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
) : null}
|
||||
</li>
|
||||
));
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ export type ChatMessages = {
|
||||
message_id: number;
|
||||
tempId: string;
|
||||
pending: boolean;
|
||||
attachment: string | null;
|
||||
attachment_url: string | null;
|
||||
};
|
||||
type ContactsProps = {
|
||||
usernamecontact: string;
|
||||
|
||||
@@ -45,10 +45,10 @@ async function createTables() {
|
||||
CREATE TABLE IF NOT EXISTS messages (
|
||||
sender VARCHAR(128) NOT NULL,
|
||||
recipient VARCHAR(128) NOT NULL,
|
||||
message VARCHAR(10000) NOT NULL,
|
||||
message TEXT NOT NULL,
|
||||
timestamp TIMESTAMPTZ DEFAULT NOW(),
|
||||
message_id SERIAL PRIMARY KEY,
|
||||
attachment VARCHAR(1000),
|
||||
attachment_url TEXT,
|
||||
UNIQUE (sender, recipient, message_id)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_messages_conversation
|
||||
@@ -99,14 +99,19 @@ async function getUserId(username) {
|
||||
console.error("Failed to get user id", e);
|
||||
}
|
||||
}
|
||||
async function insertMessage(sender, recipient, message) {
|
||||
async function insertMessage(sender, recipient, message, attachmentUrl) {
|
||||
const query = `
|
||||
INSERT INTO messages (sender, recipient, message)
|
||||
VALUES ($1, $2, $3)
|
||||
RETURNING message, timestamp, message_id;
|
||||
INSERT INTO messages (sender, recipient, message, attachment_url)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING message, timestamp, message_id, attachment_url;
|
||||
`;
|
||||
try {
|
||||
const results = await client.query(query, [sender, recipient, message]);
|
||||
const results = await client.query(query, [
|
||||
sender,
|
||||
recipient,
|
||||
message,
|
||||
attachmentUrl,
|
||||
]);
|
||||
return results.rows[0];
|
||||
} catch (e) {
|
||||
console.error("Failed to insert message ", e);
|
||||
|
||||
@@ -57,6 +57,7 @@ const storage = multer.diskStorage({
|
||||
const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9);
|
||||
const extension = extname(file.originalname);
|
||||
const finalName = uniqueSuffix + extension;
|
||||
file.finalName = finalName;
|
||||
cb(null, finalName);
|
||||
},
|
||||
});
|
||||
@@ -291,11 +292,10 @@ app.post(
|
||||
return res.status(400).json({ message: "No file specified" });
|
||||
}
|
||||
const { finalName } = req.file;
|
||||
const url = process.env.ORIGIN;
|
||||
const url = `${process.env.ORIGIN}/attachments/${finalName}`;
|
||||
res.json({
|
||||
message: "File uploaded successfully",
|
||||
attachmentUrl: req.file,
|
||||
url: url,
|
||||
attachment_url: url,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
@@ -63,15 +63,28 @@ function initializeSocket(io) {
|
||||
socket.join(username); // join username room
|
||||
|
||||
socket.on("chat message", async (msg, callback) => {
|
||||
const { message, recipient } = msg;
|
||||
const { message, recipient, attachment_url } = msg;
|
||||
const sender = username;
|
||||
if (!message || !recipient) {
|
||||
callback({ status: "error", message: "Invalid message or recipient" });
|
||||
|
||||
if (!message && !attachment_url) {
|
||||
callback({
|
||||
status: "error",
|
||||
message: "No message or attachment provided",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!recipient) {
|
||||
callback({ status: "error", message: "No recipient provided" });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const insertedMessage = await insertMessage(sender, recipient, message);
|
||||
const insertedMessage = await insertMessage(
|
||||
sender,
|
||||
recipient,
|
||||
message,
|
||||
attachment_url,
|
||||
);
|
||||
if (!insertedMessage) {
|
||||
callback({ status: "error", message: "Failed to insert message" });
|
||||
return;
|
||||
@@ -83,18 +96,24 @@ function initializeSocket(io) {
|
||||
io.to(username).to(recipient).emit("chat message", {
|
||||
sender,
|
||||
message,
|
||||
attachment_url,
|
||||
recipient,
|
||||
message_id,
|
||||
});
|
||||
console.log("(socket) sent on 'chat message' socket: ", {
|
||||
sender,
|
||||
message,
|
||||
attachment_url,
|
||||
recipient,
|
||||
timestamp,
|
||||
message_id,
|
||||
});
|
||||
|
||||
callback({ status: "ok", tempId: msg.tempId });
|
||||
callback({
|
||||
status: "ok",
|
||||
tempId: msg.tempId,
|
||||
message: "Received message",
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("(socket) Failed to insert message ", e);
|
||||
callback({ status: "error", message: "Internal server error" });
|
||||
|
||||
Reference in New Issue
Block a user