Skip to content

Commit d6b5739

Browse files
authored
/chat/:idにアクセス可能に (#535)
# PRの概要 ## 具体的な変更内容 close #521 ## 影響範囲 ## 動作要件 ## 補足 app/chat/[id]/page.tsxにおいて、処理をhookにまとめる必要があるが、なんかうまくいかなかったので、放置してる あと、型とかやばそう ## レビューリクエストを出す前にチェック! - [ ] 改めてセルフレビューしたか - [ ] 手動での動作検証を行ったか - [ ] server の機能追加ならば、テストを書いたか - 理由: 書いた | server の機能追加ではない - [ ] 間違った使い方が存在するならば、それのドキュメントをコメントで書いたか - 理由: 書いた | 間違った使い方は存在しない - [ ] わかりやすいPRになっているか <!-- レビューリクエスト後は、Slackでもメンションしてお願いすることを推奨します。 -->
1 parent 03aff82 commit d6b5739

File tree

10 files changed

+107
-62
lines changed

10 files changed

+107
-62
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ jobs:
8686
- uses: actions/setup-node@v3
8787
- uses: oven-sh/setup-bun@v2
8888
- run: make prepare-deploy-web
89-
- run: test `ls web/out | wc -l` != 0
89+
- run: test `ls web/.next | wc -l` != 0
9090

9191
deploy-test-server:
9292
name: Deploy Test (server)

web/api/chat/chat.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,22 @@ export async function sendDM(
8383
return res.json();
8484
}
8585

86-
export async function getDM(friendId: UserID): Promise<DMRoom> {
86+
export async function getDM(friendId: UserID): Promise<
87+
DMRoom & {
88+
name: string;
89+
thumbnail: string;
90+
}
91+
> {
8792
const res = await credFetch("GET", endpoints.dmWith(friendId));
8893
if (res.status === 401) throw new ErrUnauthorized();
8994
if (res.status !== 200)
9095
throw new Error(
9196
`getDM() failed: expected status code 200, got ${res.status}`,
9297
);
93-
const json: DMRoom = await res.json();
98+
const json: DMRoom & {
99+
name: string;
100+
thumbnail: string;
101+
} = await res.json();
94102
if (!Array.isArray(json?.messages)) return json;
95103
for (const m of json.messages) {
96104
m.createdAt = new Date(m.createdAt);

web/app/chat/[id]/page.tsx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"use client";
2+
import { useEffect, useState } from "react";
3+
import * as chat from "~/api/chat/chat";
4+
import { RoomWindow } from "~/components/chat/RoomWindow";
5+
6+
export default function Page({ params }: { params: { id: string } }) {
7+
const id = Number.parseInt(params.id);
8+
const [room, setRoom] = useState<
9+
| ({
10+
id: number;
11+
isDM: true;
12+
messages: {
13+
id: number;
14+
creator: number;
15+
createdAt: Date;
16+
content: string;
17+
edited: boolean;
18+
}[];
19+
} & {
20+
name: string;
21+
thumbnail: string;
22+
})
23+
| null
24+
>(null);
25+
useEffect(() => {
26+
(async () => {
27+
const room = await chat.getDM(id);
28+
setRoom(room);
29+
})();
30+
}, [id]);
31+
32+
return (
33+
<>
34+
<p>idは{id}です。</p>
35+
{room ? <RoomWindow friendId={id} room={room} /> : <p>データないよ</p>}
36+
</>
37+
);
38+
}

web/app/chat/page.tsx

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
"use client";
22

3-
import { useSearchParams } from "next/navigation";
43
import { Suspense } from "react";
54
import { useRoomsOverview } from "~/api/chat/hooks";
65
import RoomList from "~/components/chat/RoomList";
7-
import { RoomWindow } from "~/components/chat/RoomWindow";
86
import FullScreenCircularProgress from "~/components/common/FullScreenCircularProgress";
97

108
export default function Chat() {
@@ -16,18 +14,8 @@ export default function Chat() {
1614
}
1715

1816
function ChatListContent() {
19-
const searchParams = useSearchParams();
20-
21-
const friendId = searchParams.get("friendId");
22-
2317
const { state } = useRoomsOverview();
24-
25-
return friendId ? (
26-
<>
27-
<p>Chat - friend Id: {friendId}</p>
28-
<RoomWindow />
29-
</>
30-
) : state.current === "loading" ? (
18+
return state.current === "loading" ? (
3119
<FullScreenCircularProgress />
3220
) : state.current === "error" ? (
3321
<p className="decoration-red">Error: {state.error.message}</p>

web/components/chat/MessageInput.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
1-
import type { DMOverview, SendMessage, UserID } from "common/types";
1+
import type { SendMessage, UserID } from "common/types";
22
import { parseContent } from "common/zod/methods";
33
import { useEffect, useState } from "react";
44
import { MdSend } from "react-icons/md";
55

66
type Props = {
77
send: (to: UserID, m: SendMessage) => void;
8-
room: DMOverview;
8+
friendId: UserID;
99
};
1010

1111
const crossRoomMessageState = new Map<number, string>();
1212

13-
export function MessageInput({ send, room }: Props) {
13+
export function MessageInput({ send, friendId }: Props) {
1414
const [message, _setMessage] = useState<string>("");
1515
const [error, setError] = useState<string | null>(null);
1616

1717
function setMessage(m: string) {
1818
_setMessage(m);
19-
crossRoomMessageState.set(room.friendId, m);
19+
crossRoomMessageState.set(friendId, m);
2020
}
2121

2222
useEffect(() => {
23-
_setMessage(crossRoomMessageState.get(room.friendId) || "");
24-
}, [room.friendId]);
23+
_setMessage(crossRoomMessageState.get(friendId) || "");
24+
}, [friendId]);
2525

2626
function submit(e: React.FormEvent) {
2727
e.preventDefault();
@@ -34,7 +34,7 @@ export function MessageInput({ send, room }: Props) {
3434
}
3535

3636
if (message.trim()) {
37-
send(room.friendId, { content: message });
37+
send(friendId, { content: message });
3838
setMessage("");
3939
}
4040
}
@@ -50,7 +50,7 @@ export function MessageInput({ send, room }: Props) {
5050
return;
5151
}
5252
if (message.trim()) {
53-
send(room.friendId, { content: message });
53+
send(friendId, { content: message });
5454
setMessage("");
5555
}
5656
}

web/components/chat/RoomHeader.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
1-
import type { DMOverview } from "common/types";
21
import Link from "next/link";
32
import { MdArrowBack } from "react-icons/md";
43
import UserAvatar from "../human/avatar";
54

65
type Props = {
7-
room: DMOverview;
6+
room: {
7+
isDM: true;
8+
id: number;
9+
messages: {
10+
id: number;
11+
creator: number;
12+
createdAt: Date;
13+
content: string;
14+
edited: boolean;
15+
}[];
16+
} & {
17+
name: string;
18+
thumbnail: string;
19+
};
820
};
921

1022
export function RoomHeader(props: Props) {

web/components/chat/RoomList.tsx

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,8 @@ type RoomListProps = {
1212
export function RoomList(props: RoomListProps) {
1313
const { roomsData } = props;
1414
const router = useRouter();
15-
16-
/**
17-
* FIXME:
18-
* React Router が使えなくなったので、一時的に room の情報を URL に載せることで状態管理
19-
*/
2015
const navigateToRoom = (room: Extract<RoomOverview, { isDM: true }>) => {
21-
router.push(
22-
`./?friendId=${room.friendId}&roomData=${encodeURIComponent(JSON.stringify(room))}`,
23-
);
16+
router.push(`/chat/${room.friendId}`);
2417
};
2518

2619
return (

web/components/chat/RoomWindow.tsx

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
1-
import type {
2-
DMOverview,
3-
Message,
4-
MessageID,
5-
SendMessage,
6-
UserID,
7-
} from "common/types";
1+
"use client";
2+
import type { Message, MessageID, SendMessage, UserID } from "common/types";
83
import type { Content } from "common/zod/types";
9-
import { useSearchParams } from "next/navigation";
104
import { useSnackbar } from "notistack";
115
import { useCallback, useEffect, useRef, useState } from "react";
126
import * as chat from "~/api/chat/chat";
@@ -19,13 +13,25 @@ import { socket } from "../data/socket";
1913
import { MessageInput } from "./MessageInput";
2014
import { RoomHeader } from "./RoomHeader";
2115

22-
export function RoomWindow() {
23-
// FIXME: React Router が使えなくなったので、一時的に room の情報を URL に載せることで状態管理
24-
const searchParams = useSearchParams();
25-
const roomData = searchParams.get("roomData");
26-
const room = roomData
27-
? (JSON.parse(decodeURIComponent(roomData)) as DMOverview)
28-
: null;
16+
type Props = {
17+
friendId: UserID;
18+
room: {
19+
id: number;
20+
messages: {
21+
id: number;
22+
creator: number;
23+
createdAt: Date;
24+
content: string;
25+
edited: boolean;
26+
}[];
27+
isDM: true;
28+
} & {
29+
name: string;
30+
thumbnail: string;
31+
};
32+
};
33+
export function RoomWindow(props: Props) {
34+
const { friendId, room } = props;
2935

3036
if (!room) {
3137
return (
@@ -36,7 +42,7 @@ export function RoomWindow() {
3642
const {
3743
state: { data: myId },
3844
} = useMyID();
39-
const { state, reload, write } = useMessages(room.friendId);
45+
const { state, reload, write } = useMessages(friendId);
4046
const [messages, setMessages] = useState(state.data);
4147

4248
useEffect(() => {
@@ -73,7 +79,7 @@ export function RoomWindow() {
7379
const idToken = await getIdToken();
7480
socket.emit("register", idToken);
7581
socket.on("newMessage", async (msg: Message) => {
76-
if (msg.creator === room.friendId) {
82+
if (msg.creator === friendId) {
7783
appendLocalMessage(msg);
7884
} else {
7985
const creator = await user.get(msg.creator);
@@ -87,7 +93,7 @@ export function RoomWindow() {
8793
}
8894
});
8995
socket.on("updateMessage", async (msg: Message) => {
90-
if (msg.creator === room.friendId) {
96+
if (msg.creator === friendId) {
9197
updateLocalMessage(msg);
9298
}
9399
});
@@ -104,6 +110,7 @@ export function RoomWindow() {
104110
};
105111
}, [
106112
room,
113+
friendId,
107114
enqueueSnackbar,
108115
appendLocalMessage,
109116
updateLocalMessage,
@@ -142,11 +149,11 @@ export function RoomWindow() {
142149
const editedMessage = await chat.updateMessage(
143150
message,
144151
{ content },
145-
room.friendId,
152+
friendId,
146153
);
147154
updateLocalMessage(editedMessage);
148155
},
149-
[updateLocalMessage, room.friendId],
156+
[updateLocalMessage, friendId],
150157
);
151158

152159
const cancelEdit = useCallback(() => {
@@ -167,7 +174,7 @@ export function RoomWindow() {
167174
<div className="fixed top-14 z-50 w-full bg-white">
168175
<RoomHeader room={room} />
169176
</div>
170-
<div className="absolute top-14 right-0 bottom-14 left-0 flex flex-col overflow-y-auto">
177+
<div className="absolute top-14 right-0 left-0 flex flex-col overflow-y-auto">
171178
{messages && messages.length > 0 ? (
172179
<div className="flex-grow overflow-y-auto p-2" ref={scrollDiv}>
173180
{messages.map((m) => (
@@ -225,7 +232,7 @@ export function RoomWindow() {
225232
{
226233
label: "削除",
227234
color: "red",
228-
onClick: () => deleteMessage(m.id, room.friendId),
235+
onClick: () => deleteMessage(m.id, friendId),
229236
alert: true,
230237
messages: {
231238
buttonMessage: "削除",
@@ -248,8 +255,8 @@ export function RoomWindow() {
248255
</div>
249256
)}
250257
</div>
251-
<div className="fixed bottom-0 w-full bg-white p-0">
252-
<MessageInput send={sendDMMessage} room={room} />
258+
<div className="fixed bottom-12 w-full bg-white p-0">
259+
<MessageInput send={sendDMMessage} friendId={friendId} />
253260
</div>
254261
</>
255262
);

web/firebase/auth/lib.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ const token = new Promise<string>((resolve) => {
1717
});
1818

1919
export async function getIdToken(): Promise<IDToken> {
20-
return await token;
20+
const toke = await token;
21+
return toke;
2122
}
2223

2324
type RequestMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";

web/next.config.mjs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
/** @type {import('next').NextConfig} */
2-
const nextConfig = {
3-
output: "export",
4-
};
2+
const nextConfig = {};
53

64
export default nextConfig;

0 commit comments

Comments
 (0)