Skip to content

Commit 82766b5

Browse files
committed
merge main
2 parents af13e54 + 1fb12e0 commit 82766b5

File tree

12 files changed

+118
-69
lines changed

12 files changed

+118
-69
lines changed

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ test: dev-db
4747

4848
prepare-deploy-web: sync-common
4949
cd web; bun install; bun run build
50+
deploy-web:
51+
@if [ "${PORT}" == "" ]; then echo 'env PORT not found!'; exit 1; fi
52+
cd web; bun next start --port ${PORT}
5053
prepare-deploy-server: sync-common sync-server generate-sql
5154
deploy-server:
5255
cd server; bun src/main.ts

server/src/database/chat.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,6 @@ export async function markAsRead(
127127
reader: UserID,
128128
message: MessageID,
129129
) {
130-
const val = {
131-
readerId: reader,
132-
messageId: message,
133-
relationId: rel,
134-
};
135130
return await prisma.message.updateMany({
136131
where: {
137132
id: {
@@ -161,6 +156,7 @@ export async function sendDM(
161156
try {
162157
const message = await prisma.message.create({
163158
data: {
159+
// isPicture: false, // todo: bring it back
164160
relationId: relation,
165161
isPicture: false,
166162
read: false,

server/src/functions/chat.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export async function sendDM(
5656
};
5757

5858
const result = await db.sendDM(rel.value.id, msg);
59-
if (!result.ok) return http.internalError("");
59+
if (!result.ok) return http.internalError("Failed to send DM");
6060
return http.created(result.value);
6161
}
6262

server/src/lib/socket/socket.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,24 @@ export function initializeSocket(server: Server, corsOptions: CorsOptions) {
1313
});
1414

1515
io.on("connection", (socket) => {
16+
console.log(`New connection created of id ${socket.id}`);
1617
socket.on("register", async (token) => {
1718
const userId = await getUserIdFromToken(token);
1819
if (userId) {
1920
users.set(userId, socket);
21+
console.log(
22+
`The user of id ${socket.id} turned out to have id ${userId}`,
23+
);
2024
} else {
2125
console.log("Invalid token or failed to retrieve user ID");
2226
}
2327
});
2428

2529
socket.on("disconnect", () => {
30+
console.log(`A user disconnected of id ${socket.id}`);
2631
for (const [id, socket2] of users.entries()) {
2732
if (socket2.id === socket.id) {
33+
console.log(`... whose userId is ${id}`);
2834
users.delete(id);
2935
break;
3036
}

server/src/router/chat.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ router.post("/dm/to/:userid", async (req, res) => {
3838

3939
const result = await core.sendDM(user.value, friend.value, send.data);
4040
if (result.ok) {
41-
ws.sendMessage(result?.body, friend.value);
41+
ws.sendMessage(result.body, friend.value);
4242
}
4343
res.status(result.code).send(result.body);
4444
});

server/src/router/picture.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ router.get("/profile/:guid", async (req, res) => {
7272
const result = await storage.getProf(guid);
7373
switch (result.ok) {
7474
case true:
75-
return res.send(result.value);
75+
return res.send(new Buffer(result.value));
7676
case false:
7777
return res.status(404).send();
7878
}

web/api/internal/endpoints.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import type { CourseID, Day, GUID } from "common/types";
22
import type { MessageID, ShareRoomID } from "common/types";
3+
import { panic } from "~/lib/utils";
34

4-
export const API_ENDPOINT: string | null =
5-
process.env.NEXT_PUBLIC_API_ENDPOINT ?? "";
6-
if (!API_ENDPOINT)
7-
throw new Error("process.env.NEXT_PUBLIC_API_ENDPOINT not found!");
5+
export const API_ENDPOINT: string =
6+
process.env.NEXT_PUBLIC_API_ENDPOINT ??
7+
panic("process.env.NEXT_PUBLIC_API_ENDPOINT not found!");
88

99
// TODO: de-export this and use one from /common
1010
export type UserID = number;
@@ -375,6 +375,7 @@ export const sendPictureTo = (friendId: UserID) =>
375375
*/
376376
export const profilePictureOf = (guid: GUID) =>
377377
`${API_ENDPOINT}/picture/profile/${guid}`;
378+
export const pictureOf = (guid: GUID) => `${API_ENDPOINT}/picture/${guid}`;
378379

379380
/**
380381
* POST: update my profile picture.

web/components/chat/RoomWindow.tsx

Lines changed: 25 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,14 @@
22
import type { Message, MessageID, SendMessage, UserID } from "common/types";
33
import type { Content, DMOverview, DMRoom } from "common/zod/types";
44
import { useRouter } from "next/navigation";
5-
import { useSnackbar } from "notistack";
65
import { useCallback, useEffect, useRef, useState } from "react";
76
import * as chat from "~/api/chat/chat";
87
import { useMessages } from "~/api/chat/hooks";
98
import { API_ENDPOINT } from "~/api/internal/endpoints";
109
import request from "~/api/request";
11-
import * as user from "~/api/user";
1210
import { useMyID } from "~/api/user";
13-
import { getIdToken } from "~/firebase/auth/lib";
1411
import Dots from "../common/Dots";
15-
import { socket } from "../data/socket";
12+
import { handlers } from "../data/socket";
1613
import { MessageInput } from "./MessageInput";
1714
import { RoomHeader } from "./RoomHeader";
1815

@@ -48,7 +45,6 @@ export function RoomWindow(props: Props) {
4845
setMessages(state.data);
4946
}, [state.data]);
5047

51-
const { enqueueSnackbar } = useSnackbar();
5248
const [editingMessageId, setEditingMessageId] = useState<number | null>(null);
5349
const [editedContent, setEditedContent] = useState<string>("");
5450

@@ -69,54 +65,35 @@ export function RoomWindow(props: Props) {
6965
},
7066
[write],
7167
);
72-
const updateLocalMessage = useCallback((_: Message) => reload(), [reload]);
68+
// TODO: fix these
69+
const updateLocalMessage = useCallback(
70+
(_a: MessageID, _: Message) => reload(),
71+
[reload],
72+
);
7373
const deleteLocalMessage = useCallback((_: MessageID) => reload(), [reload]);
7474

75+
// メッセージの受取
7576
useEffect(() => {
76-
async function registerSocket() {
77-
if (!room) return;
78-
const idToken = await getIdToken();
79-
socket.emit("register", idToken);
80-
socket.on("newMessage", async (msg: Message) => {
81-
if (msg.creator === friendId) {
82-
appendLocalMessage(msg);
83-
} else {
84-
const creator = await user.get(msg.creator);
85-
if (creator == null) return;
86-
enqueueSnackbar(
87-
`${creator.name}さんからのメッセージ : ${msg.content}`,
88-
{
89-
variant: "info",
90-
},
91-
);
92-
}
93-
});
94-
socket.on("updateMessage", async (msg: Message) => {
95-
if (msg.creator === friendId) {
96-
updateLocalMessage(msg);
97-
}
98-
});
99-
socket.on("deleteMessage", async (msgId: number) => {
100-
deleteLocalMessage(msgId);
101-
});
102-
}
103-
registerSocket();
104-
// Clean up
77+
handlers.onCreate = (msg) => {
78+
if (msg.creator === friendId) {
79+
appendLocalMessage(msg);
80+
return true; // caught
81+
}
82+
return false; // didn't catch
83+
};
84+
handlers.onUpdate = (id, msg) => {
85+
updateLocalMessage(id, msg);
86+
};
87+
handlers.onDelete = (id) => {
88+
deleteLocalMessage(id);
89+
};
10590
return () => {
106-
socket.off("newMessage");
107-
socket.off("updateMessage");
108-
socket.off("deleteMessage");
91+
handlers.onCreate = undefined;
92+
handlers.onDelete = undefined;
10993
};
110-
}, [
111-
room,
112-
friendId,
113-
enqueueSnackbar,
114-
appendLocalMessage,
115-
updateLocalMessage,
116-
deleteLocalMessage,
117-
]);
94+
}, [friendId, appendLocalMessage, updateLocalMessage, deleteLocalMessage]);
11895

119-
//画面スクロール
96+
// 画面スクロール
12097
const scrollDiv = useRef<HTMLDivElement>(null);
12198
const scrollToBottom = useCallback(() => {
12299
if (scrollDiv.current) {
@@ -150,7 +127,7 @@ export function RoomWindow(props: Props) {
150127
{ content },
151128
friendId,
152129
);
153-
updateLocalMessage(editedMessage);
130+
updateLocalMessage(editedMessage.id, editedMessage);
154131
},
155132
[updateLocalMessage, friendId],
156133
);

web/components/data/socket.ts

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,43 @@
1+
import type { Message } from "common/types";
2+
import { enqueueSnackbar } from "notistack";
13
import { io } from "socket.io-client";
4+
import { API_ENDPOINT } from "~/api/internal/endpoints";
5+
import * as user from "~/api/user";
6+
import { getIdToken } from "~/firebase/auth/lib";
27

3-
const URL = process.env.NEXT_PUBLIC_API_ENDPOINT;
4-
5-
if (!URL) {
6-
throw new Error("process.env.NEXT_PUBLIC_API_ENDPOINT not found!");
7-
}
8-
9-
export const socket = io(URL, {
8+
export const socket = io(API_ENDPOINT, {
109
auth: {
1110
serverOffset: 0, //TODO: ちゃんと実装する
1211
},
1312
});
13+
14+
export const handlers: {
15+
onCreate: undefined | ((data: Message) => boolean); // should return if it matched
16+
onUpdate: undefined | ((id: number, data: Message) => void);
17+
onDelete: undefined | ((id: number) => void);
18+
} = {
19+
onCreate: undefined,
20+
onUpdate: undefined,
21+
onDelete: undefined,
22+
};
23+
24+
(async () => {
25+
const idToken = await getIdToken();
26+
socket.emit("register", idToken);
27+
})();
28+
socket.on("newMessage", async (msg: Message) => {
29+
if (handlers.onCreate?.(msg)) return; // if it exists and caught the create sig
30+
31+
const creator = await user.get(msg.creator);
32+
if (!creator) return;
33+
enqueueSnackbar(`${creator.name}さんからのメッセージ : ${msg.content}`, {
34+
variant: "info",
35+
});
36+
});
37+
38+
socket.on("updateMessage", async (msg: Message) => {
39+
if (handlers.onUpdate) handlers.onUpdate(msg.id, msg);
40+
});
41+
socket.on("deleteMessage", async (msgId: number) => {
42+
if (handlers.onDelete) handlers.onDelete(msgId);
43+
});

web/components/human/humanListItem.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type HumanListItemProps = {
1414
onAccept?: (id: number) => void;
1515
onReject?: (id: number) => void;
1616
onCancel?: (id: number) => void;
17+
onRequest?: (id: number) => void;
1718
hasDots?: boolean;
1819
dotsActions?: object;
1920
};
@@ -32,6 +33,7 @@ export function HumanListItem(props: HumanListItemProps) {
3233
onAccept,
3334
onReject,
3435
onCancel,
36+
onRequest,
3537
hasDots,
3638
} = props;
3739

@@ -70,7 +72,7 @@ export function HumanListItem(props: HumanListItemProps) {
7072
)}
7173
</div>
7274
</button>
73-
<div className="flex items-center space-x-2">
75+
<div className="mr-3 flex items-center space-x-2">
7476
{unreadCount ? (
7577
<span className="badge badge-primary">{unreadCount}</span>
7678
) : undefined}
@@ -107,6 +109,15 @@ export function HumanListItem(props: HumanListItemProps) {
107109
キャンセル
108110
</button>
109111
)}
112+
{onRequest && (
113+
// biome-ignore lint/a11y/useButtonType: <explanation>
114+
<button
115+
className="btn btn-sm bg-primary text-white"
116+
onClick={() => onRequest(id)}
117+
>
118+
リクエスト
119+
</button>
120+
)}
110121
{hasDots && (
111122
<Dots
112123
actions={[

0 commit comments

Comments
 (0)