Skip to content

Commit 69f7dc1

Browse files
authored
Merge pull request #51 from kc3hack/fix
uiを修正
2 parents 5d09c61 + 762b9ad commit 69f7dc1

10 files changed

Lines changed: 154 additions & 61 deletions

File tree

apps/web/src/components/animations/SlidingGhost.tsx

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ const ghostContainerClass = css`
2828
bottom: 16px;
2929
}
3030
31+
@media (max-width: 600px) {
32+
&.mobile-middle {
33+
bottom: clamp(9.5rem, 29vh, 14rem);
34+
transform: translateX(50%) scale(0.43);
35+
}
36+
}
37+
3138
&.is-entering {
3239
animation: ${slideInFromRight} 1.2s cubic-bezier(0.22, 0.9, 0.22, 1) both;
3340
}
@@ -39,12 +46,12 @@ const ghostContainerClass = css`
3946
}
4047
4148
&.is-entering-left {
42-
animation: ${slideInFromLeft} 1.2s cubic-bezier(0.22, 0.9, 0.22, 1) both;
49+
animation: ${slideInFromLeft} 3.2s cubic-bezier(0.22, 0.9, 0.22, 1) both;
4350
}
4451
4552
@media (max-width: 600px) {
4653
&.is-entering-left {
47-
animation: ${slideInFromLeftMobile} 1.2s cubic-bezier(0.22, 0.9, 0.22, 1) both;
54+
animation: ${slideInFromLeftMobile} 3.2s cubic-bezier(0.22, 0.9, 0.22, 1) both;
4855
}
4956
}
5057
@@ -57,6 +64,10 @@ const ghostContainerClass = css`
5764
}
5865
}
5966
67+
&.is-moving.is-moving-slow {
68+
transition-duration: 3.4s;
69+
}
70+
6071
&.is-sleeping {
6172
pointer-events: none;
6273
}
@@ -81,11 +92,11 @@ const ghostContainerClass = css`
8192
opacity: 1;
8293
}
8394
84-
&.is-moving .ghost-eye {
95+
&.is-moving.use-wake-eye .ghost-eye {
8596
opacity: 0;
8697
}
8798
88-
&.is-moving .wake-eye {
99+
&.is-moving.use-wake-eye .wake-eye {
89100
opacity: 1;
90101
}
91102
@@ -273,6 +284,9 @@ type Props = {
273284
showNotes?: boolean;
274285
enteringFromRight?: boolean;
275286
enteringFromLeft?: boolean;
287+
wakeEyesOnMove?: boolean;
288+
slowMove?: boolean;
289+
mobilePlacement?: "bottom" | "button";
276290
};
277291

278292
export const SlidingGhost = ({
@@ -281,12 +295,17 @@ export const SlidingGhost = ({
281295
showNotes = false,
282296
enteringFromRight = false,
283297
enteringFromLeft = false,
298+
wakeEyesOnMove = true,
299+
slowMove = false,
300+
mobilePlacement = "bottom",
284301
}: Props) => {
285302
const bodyId = "sliding-ghost-body";
286303
const isInteractive = !isMoving && !isSleeping;
287304
const className = `${ghostContainerClass} ${isMoving ? "is-moving" : ""} ${isSleeping ? "is-sleeping" : ""} ${
288305
enteringFromRight ? "is-entering" : ""
289-
} ${enteringFromLeft ? "is-entering-left" : ""}`;
306+
} ${enteringFromLeft ? "is-entering-left" : ""} ${wakeEyesOnMove ? "use-wake-eye" : ""} ${
307+
slowMove ? "is-moving-slow" : ""
308+
} ${mobilePlacement === "button" ? "mobile-middle" : ""}`;
290309

291310
return (
292311
<div class={className}>

apps/web/src/components/animations/TransferHandoverScene.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ const handoverClass = css`
144144
.green-ghost {
145145
left: -48%;
146146
transform: scale(0.44);
147-
transition: left 1.55s cubic-bezier(0.2, 0.9, 0.22, 1);
147+
transition: left 2.9s cubic-bezier(0.2, 0.9, 0.22, 1);
148148
}
149149
150150
.orange-ghost {
@@ -168,31 +168,31 @@ const handoverClass = css`
168168
}
169169
170170
&.is-active .orange-ghost {
171-
animation: ${orangeArrival} 1.05s cubic-bezier(0.24, 1, 0.38, 1) forwards;
171+
animation: ${orangeArrival} 2.3s cubic-bezier(0.24, 1, 0.38, 1) forwards;
172172
}
173173
174174
&.is-active .green-arm-left {
175175
transform: rotate(-73deg) translate(10px, 22px);
176-
transition-delay: 1.68s;
176+
transition-delay: 3.15s;
177177
}
178178
179179
&.is-active .orange-arm-right {
180180
transform: rotate(58deg) translate(16px, -10px);
181-
transition-delay: 2.05s;
181+
transition-delay: 4.45s;
182182
}
183183
184184
&.is-active .orange-arm-left {
185185
transform: rotate(-58deg) translate(-16px, -10px);
186-
transition-delay: 2.05s;
186+
transition-delay: 4.45s;
187187
}
188188
189189
&.is-active .letter-item {
190-
animation: ${letterAppear} 0.65s cubic-bezier(0.24, 1, 0.38, 1) 1.95s forwards;
190+
animation: ${letterAppear} 1.05s cubic-bezier(0.24, 1, 0.38, 1) 3.75s forwards;
191191
}
192192
193193
&.is-active .orange-ghost .cheek {
194194
opacity: 0.78;
195-
transition-delay: 2.14s;
195+
transition-delay: 4.6s;
196196
}
197197
198198
@media (max-width: 600px) {

apps/web/src/components/button/FileSelectArea.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ const containerStyles = css`
1616
1717
/* モバイル対応:さらにコンパクトに */
1818
@media (max-width: 600px) {
19-
max-width: 280px; /* 横幅を絞る */
20-
padding: 1.2rem 1rem;
21-
gap: 0.5rem;
22-
border-width: 4px; /* 枠線を少し細く */
19+
width: min(94vw, 21rem);
20+
max-width: 21rem;
21+
padding: 1.45rem 1.1rem;
22+
gap: 0.65rem;
23+
border-width: 4px;
2324
}
2425
`;
2526

@@ -41,8 +42,8 @@ const dropZoneStyles = css`
4142
box-sizing: border-box;
4243
4344
@media (max-width: 600px) {
44-
padding: 1.5rem 0.5rem;
45-
font-size: 1rem; /* 文字を小さく */
45+
padding: 1.7rem 0.7rem;
46+
font-size: 1.08rem;
4647
}
4748
4849
&:hover {
@@ -67,7 +68,7 @@ export const FileSelectArea = ({ onSelect }: Props) => {
6768

6869
<span style="color: #fff; font-weight: bold; font-size: 1.1rem;">または</span>
6970

70-
<div style="width: 100%; display: flex; justify-content: center; transform: scale(0.8);">
71+
<div style="width: 100%; display: flex; justify-content: center; transform: scale(0.8);" class="file-select-btn">
7172
<GreenButton text="ファイルを選択" onClick={onSelect} />
7273
</div>
7374
</div>

apps/web/src/components/button/PinInputBlock.tsx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ const containerStyles = css`
1515
margin: 0 auto;
1616
1717
@media (max-width: 600px) {
18-
max-width: 300px;
19-
padding: 1.5rem 1rem;
18+
width: min(95vw, 22.4rem);
19+
max-width: 22.4rem;
20+
padding: 1.65rem 1.15rem;
2021
border-width: 4px;
2122
}
2223
`;
@@ -34,8 +35,13 @@ const titleStyles = css`
3435

3536
const pinContainerStyles = css`
3637
display: flex;
38+
width: 100%;
3739
gap: 0.5rem;
3840
justify-content: center;
41+
42+
@media (max-width: 600px) {
43+
gap: 0.38rem;
44+
}
3945
`;
4046

4147
const pinInputStyles = css`
@@ -58,9 +64,9 @@ const pinInputStyles = css`
5864
}
5965
6066
@media (max-width: 600px) {
61-
width: 2.2rem;
62-
height: 3rem;
63-
font-size: 1.5rem;
67+
width: 2.28rem;
68+
height: 3.18rem;
69+
font-size: 1.45rem;
6470
}
6571
`;
6672

@@ -102,6 +108,10 @@ const helperTextStyles = css`
102108
line-height: 1.65;
103109
text-align: center;
104110
white-space: pre-line;
111+
112+
@media (max-width: 600px) {
113+
font-size: 0.98rem;
114+
}
105115
`;
106116

107117
const PIN_INPUT_KEYS = ["pin-1", "pin-2", "pin-3", "pin-4", "pin-5", "pin-6"] as const;

apps/web/src/components/button/ReceiveButton.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ export const ReceiveButton = ({ onClick }: Props) => {
2323
2424
&:hover { transform: scale(1.1); }
2525
&:active { transform: scale(0.95); }
26+
27+
@media (max-width: 600px) {
28+
margin-top: 1.05rem;
29+
font-size: 1.68rem;
30+
padding: 0.55rem 0.9rem;
31+
}
2632
`;
2733

2834
return (

apps/web/src/components/button/SendBackButton.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ export const SendBackButton = ({ onClick }: Props) => {
2424
2525
&:hover { transform: scale(1.1); }
2626
&:active { transform: scale(0.95); }
27+
28+
@media (max-width: 600px) {
29+
margin-top: 1.05rem;
30+
font-size: 1.65rem;
31+
padding: 0.55rem 0.9rem;
32+
}
2733
`;
2834

2935
return (

apps/web/src/hooks/useFileSenderConnection.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export const useFileSenderConnection = () => {
2323
const [errorMessage, setErrorMessage] = useState("");
2424
const [shortcode, setShortcode] = useState("");
2525
const [receiverJoinMethod, setReceiverJoinMethod] = useState<ReceiverJoinMethod>("unknown");
26+
const [receiverConfirmedByOk, setReceiverConfirmedByOk] = useState(false);
2627
const fileInputRef = useRef<HTMLInputElement>(null);
2728

2829
useEffect(() => {
@@ -57,6 +58,7 @@ export const useFileSenderConnection = () => {
5758
setErrorMessage("");
5859
setLastSentFile("");
5960
setReceiverJoinMethod("unknown");
61+
setReceiverConfirmedByOk(false);
6062

6163
signaling.on("connected", () => {
6264
setStateIfActive(() => setWsStatus("connected"));
@@ -160,6 +162,11 @@ export const useFileSenderConnection = () => {
160162
const joinMethod = payload.joinMethod;
161163
if (payload.type === "receiver-join-meta" && (joinMethod === "qr" || joinMethod === "code")) {
162164
setStateIfActive(() => setReceiverJoinMethod(joinMethod));
165+
return;
166+
}
167+
168+
if (payload.type === "receiver-ok") {
169+
setStateIfActive(() => setReceiverConfirmedByOk(true));
163170
}
164171
} catch {
165172
// 送信ファイルのメッセージ以外は無視する
@@ -235,6 +242,7 @@ export const useFileSenderConnection = () => {
235242
setShortcode(payload.shortcode);
236243
setErrorMessage("");
237244
setReceiverJoinMethod("unknown");
245+
setReceiverConfirmedByOk(false);
238246

239247
// モーダルを開く
240248
setUrl(uri);
@@ -261,6 +269,7 @@ export const useFileSenderConnection = () => {
261269
fileInputRef,
262270
shortcode,
263271
receiverJoinMethod,
272+
receiverConfirmedByOk,
264273
toggleOpen,
265274
closeModal,
266275
handleCreateRoom,

apps/web/src/hooks/useWebRTCConnection.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState } from "hono/jsx";
1+
import { useEffect, useRef, useState } from "hono/jsx";
22
import { fetchTurnIceServer, getSignalUrl } from "@/lib/realtime/client-utils";
33
import { FileReceiver } from "@/lib/realtime/file-transfer";
44
import { PeerConnectionManager } from "@/lib/realtime/peer-connection";
@@ -28,6 +28,7 @@ export const useWebRTCConnection = (roomId: string, entryMethod: ReceiverEntryMe
2828
const [receiveProgress, setReceiveProgress] = useState("0 / 0 bytes");
2929
const [lastReceivedFile, setLastReceivedFile] = useState("");
3030
const [errorMessage, setErrorMessage] = useState("");
31+
const dataChannelRef = useRef<RTCDataChannel | null>(null);
3132

3233
useEffect(() => {
3334
let isDisposed = false;
@@ -126,6 +127,7 @@ export const useWebRTCConnection = (roomId: string, entryMethod: ReceiverEntryMe
126127
setPeerStatus("connected");
127128
setDataChannelStatus("open");
128129
});
130+
dataChannelRef.current = channel;
129131

130132
if (!hasSharedEntryMeta && channel.readyState === "open") {
131133
hasSharedEntryMeta = true;
@@ -146,13 +148,15 @@ export const useWebRTCConnection = (roomId: string, entryMethod: ReceiverEntryMe
146148
setStateIfActive(() => {
147149
setDataChannelStatus("closed");
148150
});
151+
dataChannelRef.current = null;
149152
});
150153

151154
peerManager.on("disconnected", () => {
152155
setStateIfActive(() => {
153156
resetPeerState();
154157
setPeerStatus("disconnected");
155158
});
159+
dataChannelRef.current = null;
156160
});
157161

158162
peerManager.on("datachannel-message", (data) => {
@@ -185,11 +189,26 @@ export const useWebRTCConnection = (roomId: string, entryMethod: ReceiverEntryMe
185189

186190
return () => {
187191
isDisposed = true;
192+
dataChannelRef.current = null;
188193
signaling.disconnect();
189194
peerManager.cleanup();
190195
};
191196
}, [roomId, entryMethod]);
192197

198+
const sendControlMessage = (payload: { type: string; [key: string]: unknown }): boolean => {
199+
const channel = dataChannelRef.current;
200+
if (!channel || channel.readyState !== "open") {
201+
return false;
202+
}
203+
204+
try {
205+
channel.send(JSON.stringify(payload));
206+
return true;
207+
} catch {
208+
return false;
209+
}
210+
};
211+
193212
return {
194213
wsStatus,
195214
peerStatus,
@@ -198,5 +217,6 @@ export const useWebRTCConnection = (roomId: string, entryMethod: ReceiverEntryMe
198217
receiveProgress,
199218
lastReceivedFile,
200219
errorMessage,
220+
sendControlMessage,
201221
};
202222
};

0 commit comments

Comments
 (0)