Skip to content

Commit be005f9

Browse files
authored
Merge pull request #121 from ToyVallet/fix(user-web)-369-user-web
[TASK-369] user web ios web camera bug fix
2 parents b9889e1 + eb8206f commit be005f9

File tree

17 files changed

+87
-60
lines changed

17 files changed

+87
-60
lines changed

apps/host-admin/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ FROM node:20-alpine AS base
66
FROM base AS builder
77
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
88
RUN apk update
9-
RUN apk add --no-cache libc6-compat
9+
RUN apk add libc6-compat
1010
# Set working directory
1111
WORKDIR /app
1212
RUN yarn global add turbo@latest
@@ -17,7 +17,7 @@ RUN turbo prune host-admin --docker
1717
# Add lockfile and package.json's of isolated subworkspace
1818
FROM base AS installer
1919
RUN apk update
20-
RUN apk add --no-cache libc6-compat
20+
RUN apk add libc6-compat
2121
WORKDIR /app
2222

2323
# First install the dependencies (as they change less often)

apps/root-admin/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ FROM node:20-alpine AS base
22

33
FROM base AS builder
44
RUN apk update
5-
RUN apk add --no-cache libc6-compat
5+
RUN apk add libc6-compat
66
# Set working directory
77
WORKDIR /app
88
# Replace <your-major-version> with the major version installed in your repository. For example:
@@ -18,7 +18,7 @@ RUN turbo prune root-admin --docker
1818
# Add lockfile and package.json's of isolated subworkspace
1919
FROM base AS installer
2020
RUN apk update
21-
RUN apk add --no-cache libc6-compat
21+
RUN apk add libc6-compat
2222
WORKDIR /app
2323

2424
# First install the dependencies (as they change less often)

apps/user-web/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ FROM node:20-alpine AS base
66
FROM base AS builder
77
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
88
RUN apk update
9-
RUN apk add --no-cache libc6-compat
9+
RUN apk add libc6-compat
1010
# Set working directory
1111
WORKDIR /user
1212
RUN yarn global add turbo@latest
@@ -17,7 +17,7 @@ RUN turbo prune user-web --docker
1717
# Add lockfile and package.json's of isolated subworkspace
1818
FROM base AS installer
1919
RUN apk update
20-
RUN apk add --no-cache libc6-compat
20+
RUN apk add libc6-compat
2121
WORKDIR /user
2222

2323
# First install the dependencies (as they change less often)

apps/user-web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"@tensorflow-models/face-landmarks-detection": "^1.0.5",
3535
"@tensorflow-models/pose-detection": "^2.1.3",
3636
"@tensorflow/tfjs": "^4.20.0",
37+
"@tensorflow/tfjs-backend-cpu": "^4.20.0",
3738
"@tensorflow/tfjs-backend-webgl": "^4.20.0",
3839
"@tensorflow/tfjs-backend-webgpu": "^4.20.0",
3940
"@vladmandic/human": "^3.2.2",

apps/user-web/src/app/(backable)/facepass/start/@start/page.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Term } from '@components/facepass';
1+
import { FacePassDescriptionExample, Term } from '@components/facepass';
22
import { Icon } from '@swifty/assets';
33
import dynamic from 'next/dynamic';
44

@@ -9,7 +9,7 @@ const IsMobile = dynamic(
99

1010
export default function FacePassPage() {
1111
return (
12-
<>
12+
<main className="w-full h-dvh pb-20 overflow-auto scrollbar-hide">
1313
<div className="flex flex-col items-center justify-center">
1414
<header className="flex flex-col items-center justify-center text-center mt-20">
1515
<Icon
@@ -22,7 +22,7 @@ export default function FacePassPage() {
2222
안면 등록을 시작할게요
2323
</h1>
2424
</header>
25-
<div className="my-[88px]">
25+
<div className="my-20">
2626
<Icon
2727
name="user-web/facepass/logo"
2828
width={184}
@@ -32,7 +32,8 @@ export default function FacePassPage() {
3232
</div>
3333
</div>
3434
<Term />
35+
<FacePassDescriptionExample />
3536
<IsMobile />
36-
</>
37+
</main>
3738
);
3839
}

apps/user-web/src/app/(backable)/facepass/start/layout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ export default function FacePassLayout({ camera, start }: Props) {
2323
};
2424

2525
return (
26-
<div className="w-full h-full px-5">
27-
<Navigation title="돌아가기" bg="transparent" />
26+
<div className="w-dvw h-dvh px-5">
27+
<Navigation title="돌아가기" bg="blur" />
2828
<FacePassContext.Provider value={{ currentStep, nextStep }}>
2929
<Choose value={currentStep}>
3030
<When value="start">{start}</When>

apps/user-web/src/components/facepass/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export { default as Landmark } from './registration';
22
export { default as Term } from './start';
33
export { default as FacepassCameraAcceptCard } from './accept';
44
export { default as IsMobile } from './is-mobile';
5+
export { default as FacePassDescriptionExample } from './start/example';

apps/user-web/src/components/facepass/registration/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ import {
2525
saveImage,
2626
} from '@lib/fascepass';
2727
import type { DirectionType, ErrorMessage, FacePassImage } from '@lib/types';
28+
import { getOS } from '@swifty/shared-lib';
2829
import * as faceLandmarksDetection from '@tensorflow-models/face-landmarks-detection';
30+
import '@tensorflow/tfjs-backend-cpu';
2931
import '@tensorflow/tfjs-backend-webgl';
3032
import * as tf from '@tensorflow/tfjs-core';
3133
import { convertNewlineToJSX } from '@toss/react';
@@ -101,6 +103,7 @@ export default function FaceLandMark() {
101103
//facepass model load
102104
const loadModel = async () => {
103105
if (!videoRef.current || !canvasRef.current) return;
106+
104107
await tf.setBackend('webgl');
105108

106109
const model = faceLandmarksDetection.SupportedModels.MediaPipeFaceMesh;

apps/user-web/src/components/facepass/start/data.tsx

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,10 @@
1-
import FacePassTermIcon from '@components/facepass/start/icon';
21
import { type TermAccordion } from '@components/signup/terms-of-service/types';
3-
import { convertNewlineToJSX } from '@toss/react';
42

53
export const initialData: TermAccordion[] = [
64
{
75
id: 'fin',
86
title: '안면인증 정보 수집 및 이용 동의',
9-
content: (
10-
<div className="flex justify-center gap-[20px]">
11-
{(
12-
[
13-
{
14-
name: 'user-web/facepass/browser',
15-
text: convertNewlineToJSX('마스크 착용\n안돼요'),
16-
},
17-
{
18-
name: 'user-web/facepass/light',
19-
text: convertNewlineToJSX('밝은 공간에서\n 찍어요'),
20-
},
21-
{
22-
name: 'user-web/facepass/mask',
23-
text: convertNewlineToJSX('AOS 0.0 이상 \n IOS 0.0이상'),
24-
},
25-
{
26-
name: 'user-web/facepass/phone',
27-
text: convertNewlineToJSX('기본 브라우저\n크롬 사용 권장'),
28-
},
29-
] as const
30-
).map((item) => (
31-
<div
32-
key={item.name}
33-
className="flex flex-col justify-center items-center gap-2 w-full"
34-
>
35-
<FacePassTermIcon
36-
name={item.name}
37-
width={32}
38-
height={32}
39-
className="fill-black dark:fill-white"
40-
/>
41-
<span className="text-10 font-semibold text-center">
42-
{item.text}
43-
</span>
44-
</div>
45-
))}
46-
</div>
47-
),
7+
content: '약관내용',
488
approved: false,
499
required: true,
5010
},
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import FacePassTermIcon from '@components/facepass/start/icon';
2+
import { convertNewlineToJSX } from '@toss/react';
3+
4+
export default function ExampleComponent() {
5+
return (
6+
<div className="flex justify-between px-5 py-[22px] dark:bg-swifty-color-800 bg-swifty-color-200 rounded-xl">
7+
{(
8+
[
9+
{
10+
name: 'user-web/facepass/browser',
11+
text: convertNewlineToJSX('마스크 착용\n안돼요'),
12+
},
13+
{
14+
name: 'user-web/facepass/light',
15+
text: convertNewlineToJSX('밝은 공간에서\n 찍어요'),
16+
},
17+
{
18+
name: 'user-web/facepass/mask',
19+
text: convertNewlineToJSX('AOS 0.0 이상 \n IOS 0.0이상'),
20+
},
21+
{
22+
name: 'user-web/facepass/phone',
23+
text: convertNewlineToJSX('기본 브라우저\n크롬 사용 권장'),
24+
},
25+
] as const
26+
).map((item) => (
27+
<div
28+
key={item.name}
29+
className="flex flex-col justify-center items-center gap-2 w-full"
30+
>
31+
<FacePassTermIcon
32+
name={item.name}
33+
width={32}
34+
height={32}
35+
className="fill-black dark:fill-white"
36+
/>
37+
<span className="text-10 font-semibold text-center">{item.text}</span>
38+
</div>
39+
))}
40+
</div>
41+
);
42+
}

apps/user-web/src/components/facepass/start/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export default function Term() {
3232

3333
return (
3434
<>
35-
<div className="flex-1 pb-20">
35+
<div className="flex-1 mb-5">
3636
<Accordion className="flex flex-col gap-2.5" type="single" collapsible>
3737
{termsOfServices.map((term, index) => (
3838
<Items

apps/user-web/src/components/mypage/verification-section.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { UserInfoApi } from '@lib/types';
44
import type { VerficationAPI } from '@lib/types/certification';
55
import { openToast } from '@lib/utils';
66
import { Icon } from '@swifty/assets';
7-
import { getOS } from '@swifty/shared-lib';
7+
import { getOS, http } from '@swifty/shared-lib';
88
import { Button } from '@swifty/ui';
99
import { useRouter } from 'next/navigation';
1010

@@ -59,7 +59,7 @@ export default function VerificationSection({ user, certification }: Props) {
5959
function Link({ href, title, icon, status }: VerificationLink) {
6060
const router = useRouter();
6161

62-
const onClick = () => {
62+
const onClick = async () => {
6363
if (href === '/verification/student') {
6464
if (status === 'APPROVED') {
6565
openToast('학적 인증이 완료되었습니다.');
@@ -69,8 +69,13 @@ function Link({ href, title, icon, status }: VerificationLink) {
6969
router.push(href);
7070
}
7171
} else if (href === '/facepass/start') {
72+
const { result } = await http.get<{ result: boolean }>(
73+
'/facepass/check/facepass',
74+
);
7275
const type = getOS();
73-
if (type === 'server' || type === 'desktop') {
76+
if (result) {
77+
openToast('이미 안면인식을 등록하였습니다.');
78+
} else if (type === 'server' || type === 'desktop') {
7479
openToast('모바일 환경에서만 가능합니다.');
7580
} else {
7681
router.push(href);

apps/user-web/src/hooks/use-camera.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ const useCamera = () => {
1818
video.srcObject = stream;
1919

2020
video.onloadedmetadata = () => {
21+
video.playsInline = true;
2122
video.play();
23+
2224
adjustCanvasAndVideoSize(videoRef, canvasRef);
2325
setIsVideoLoad(true);
2426
};

apps/user-web/src/middleware.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ export async function middleware(request: NextRequest) {
3838
return NextResponse.redirect(url);
3939
}
4040
}
41+
42+
if (url.pathname.includes('facepass')) {
43+
const { result } = await http.get<{ result: boolean }>(
44+
'/facepass/check/facepass',
45+
);
46+
if (result) {
47+
url.pathname = '/mypage';
48+
return NextResponse.redirect(url);
49+
}
50+
}
4151
} else {
4252
// 로그인 하지 않았을 경우 접근해서는 안되는 페이지
4353
// 학적 인증 univ-certification, 마이페이지 mypage, 티켓팅 festival/[id]/ticketing, change-password, change-phone-number

apps/using-ticket/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ FROM node:20-alpine AS base
66
FROM base AS builder
77
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
88
RUN apk update
9-
RUN apk add --no-cache libc6-compat
9+
RUN apk add libc6-compat
1010
# Set working directory
1111
WORKDIR /ticket
1212
RUN yarn global add turbo@latest
@@ -17,7 +17,7 @@ RUN turbo prune using-ticket --docker
1717
# Add lockfile and package.json's of isolated subworkspace
1818
FROM base AS installer
1919
RUN apk update
20-
RUN apk add --no-cache libc6-compat
20+
RUN apk add libc6-compat
2121
WORKDIR /ticket
2222

2323
# First install the dependencies (as they change less often)

packages/shared-lib/src/constants/remotes/user-api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ const facepass = [
4444
'/facepass',
4545
'/facepass/check/{id}',
4646
'/facepass/identification/{id}',
47+
'/facepass/check/facepass',
4748
] as const;
4849

4950
export const userApi = [

yarn.lock

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5113,7 +5113,7 @@ __metadata:
51135113
languageName: node
51145114
linkType: hard
51155115

5116-
"@tensorflow/tfjs-backend-cpu@npm:4.20.0":
5116+
"@tensorflow/tfjs-backend-cpu@npm:4.20.0, @tensorflow/tfjs-backend-cpu@npm:^4.20.0":
51175117
version: 4.20.0
51185118
resolution: "@tensorflow/tfjs-backend-cpu@npm:4.20.0"
51195119
dependencies:
@@ -19686,6 +19686,7 @@ __metadata:
1968619686
"@tensorflow-models/face-landmarks-detection": "npm:^1.0.5"
1968719687
"@tensorflow-models/pose-detection": "npm:^2.1.3"
1968819688
"@tensorflow/tfjs": "npm:^4.20.0"
19689+
"@tensorflow/tfjs-backend-cpu": "npm:^4.20.0"
1968919690
"@tensorflow/tfjs-backend-webgl": "npm:^4.20.0"
1969019691
"@tensorflow/tfjs-backend-webgpu": "npm:^4.20.0"
1969119692
"@testing-library/jest-dom": "npm:^6.4.2"

0 commit comments

Comments
 (0)